Callback from thread to calling class - java

I currently have a class that extends Thread. In that class i get the contents of a web page (which is just JSON data) and i parse that. It depends what JSON object i get, because that determines what actions i take or what View i have to show.
But the way i'm currently doing it is i check in one class for all possible JSON request and perform actions based on that.
Example, my class kinda looks like this:
public class Communicator extends Thread
{
Thread threadToInterrupt = null;
String URL = null;
public Houses ( String URL )
{
threadToInterrupt = Thread.currentThread();
setDaemon(true);
this.URL = URL;
}
public void run()
{
// Code to get the JSON from a web page
// Finally parse the result into a String
String page = sb.toString();
JSONObject jObject = new JSONObject(page);
if ( !jObject.isNull("house") )
{
// do alot of stuff
}
else if ( !jObject.isNull("somethingelse") )
{
// do alot of other stuff
}
}
}
As you can imagine, this class would soon be cluttered with alot of JSON checks and codes. This doesn't feel like it's the right way.
I thought, maybe it's better to pass in a callback method that gets invoked? So that i could change my class to something like this:
public class Communicator extends Thread
{
Thread threadToInterrupt = null;
String URL = null;
public Houses ( String URL, String JsonString, object CallbackMethod )
{
// ... code
}
public void run()
{
// ....
JSONObject jObject = new JSONObject(page);
if ( !jObject.isNull(this.JsonString) )
{
// THen call the CallbackMethod...
CallbackMethod ( jObject );
}
}
}
public class MyClass
{
public void MyFunc()
{
(new Communicator("http://url.tld", "House", this.MyCallback)).start();
}
public void MyCallback(JSONObject jObject)
{
// Then i can perform actions here...
}
}
Not sure if that is a good idea. But if so, how do i create a callback like in my example? Is that possible somehow?

You won't use a callback, but a handler object like MyJsonHandler:
public class MyClass
{
public void MyFunc()
{
(new Communicator("http://url.tld", "House", new MyJsonHandler())).start();
}
}
public class MyJsonHandler() {
public void handle(JsonObject jo) {
// ...
}
}
Or create a new MyJsonHandler just in place when you need:
public void run()
{
// ....
JSONObject jObject = new JSONObject(page);
if ( !jObject.isNull(this.JsonString) )
{
// THen call the CallbackMethod...
new MyJsonHandler().handle(jObject);
}
}

Related

GSON store Json key in String variable

so I have this one problem with Gson I just cannot figure out.
Imagine a Json structure for handling tickets. The Json looks like this:
{
"concertTicket" : { ... some valid json object ... }
}
I wrote my parser like this:
#SerializedName("concertTicket")
JsonObject ticketContent;
This is simple. Now I have a JsonObject called ticketContent that stores the ticket related stuff.
So far so good... now there are exactly three different kinds of tickets: let's assume concertTicket, planeTicket and museumTicket.
What I want to achieve is a Parser with two variables. One storing the ticketType and another one storing the ticketContents.
I figured out the parser for the ticketContent:
#SerializedName(value="concertTicket", alternate={"planeTicket", "museumTicket"})
JsonObject ticketContent;
My question is now: Is it possible to write an annotation that returns the Json-Key as String in a variable called ticketType? Like so:
# ... what to put here ? ...
String ticketType;
So that
if its a concertTicket, the value of ticketType = "concertTicket",
if its a planeTicket, the value of ticketType = "planeTicket" and
if its a museumTicket, the value of ticketType = "museumTicket"?
--- Here is my workaround ---
#SerializedName( "concertTicket" )
private JsonObject concertTicket;
#SerializedName( "planeTicket" )
private JsonObject planeTicket;
#SerializedName( "museumTicket" )
private JsonObject museumTicket;
public enum TicketType {
concertTicket, planeTicket, museumTicket
}
/*
* since only one of the TicketTypes can be not null, return this as TicketType
*/
public TicketType getTicketType() {
if ( concertTicket != null ) {
return TicketType.concertTicket;
}
if ( planeTicket != null ) {
return TicketType.planeTicket;
}
if ( museumTicket != null ) {
return TicketType.museumTicket;
}
return null;
}
/*
* since only one of the TicketTypes can be not null, return this as content
*/
public JsonObject getTicketContent() {
if ( concertTicket != null ) {
return concertTicket;
}
if ( planeTicket != null ) {
return planeTicket;
}
if ( museumTicket != null ) {
return museumTicket;
}
return null;
}
But I'm wondering if there is a more elegant solution to this?
If you have 3 tickets, lets say:
concertTicket, planeTicket and museumTicket
then the should have a common parent/super class in common, or an Interface...
if so; then you can deserialize to the interface and then cast to the ticket type..
Example:
interface Iticket {
void printTicket();
}
public class Ticket implements Iticket {
protected String id;
protected int price;
public static void main(String[] args) {
String ticketString = "{\"id\":\"0000\", \"price\":15}";
Gson g = new Gson();
Ticket c = g.fromJson(ticketString, Concert.class);
((Concert) c).jump();
Ticket m = g.fromJson(ticketString, Museum.class);
((Museum) m).niddle();
}
#Override
public void printTicket() {
// TODO Auto-generated method stub
}
}
class Concert extends Ticket implements Iticket {
#Override
public void printTicket() {
//
System.out.println("Loud printer");
}
public void jump() {
System.out.println("jump");
}
}
class Museum extends Ticket implements Iticket {
#Override
public void printTicket() {
System.out.println("Boring printer");
}
public void niddle() {
System.out.println("niddle");
}
}

How to create custom events in Java

Even after some time trying to read and understand the topics already posted here, I am still confused on how to create events in Java.
Assuming that I have this class in C#:
public class HighlightsObjectHandler {
// Constants
private const String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Handlers
public event EventHandler HighlightsJsonChanged;
public event EventHandler HighlightsContentChanging;
public event EventHandler HighlightsContentChanged;
// Variables
private String
_json;
// Properties
public String HighlightsJson {
get {
return _json;
}
set {
if (value != _json && value != null) {
_json = value;
OnHighlightsJsonChanged( EventArgs.Empty );
ParseJson();
}
}
}
public Boolean HighlightsUpdating { get; private set; }
public List<HighlightObject> Highlights { get; private set; }
// Methods
private void ParseJson() {
JsonObject
jsonObject;
if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
OnHighlightsContentChanging( EventArgs.Empty );
// Json parsing and other stuff...
// ... it shouldn't matter for this question.
OnHighlightsContentChanged( EventArgs.Empty );
}
}
// Events
internal void OnHighlightsJsonChanged( EventArgs eventArgs ) {
if (HighlightsJsonChanged != null) {
HighlightsJsonChanged( this, eventArgs );
}
}
internal void OnHighlightsContentChanging( EventArgs eventArgs ) {
HighlightsUpdating = true;
if (HighlightsContentChanging != null) {
HighlightsContentChanging( this, eventArgs );
}
}
internal void OnHighlightsContentChanged( EventArgs eventArgs ) {
HighlightsUpdating = false;
if (HighlightsContentChanged != null) {
HighlightsContentChanged( this, eventArgs );
}
}
// Constructors
public HighlightsObjectHandler() {
Highlights = new List<HighlightObject>();
}
}
How would I make a copy of this in Java?
I somewhat understand that I need to create an interface that would hold the 3 EventHandlers that I have in this code. Then, I would have to implement that interface in the class. Let's assume that the class would have the exact same name and the result would be something like this:
public class HighlightsObjectHandler implements SomeListener { ... }
But, from what I see from tutorials and forums, they would fire, for instance, the HighlightsContentChanging directly instead of calling the OnHighlightsContentChanging ( where I would like to set a variable - HighlightsUpdating - to a value and then calling the listeners associated with the event ).
And there is where I'm losing my mind. How would I make this happen? In the Windows Phone app, that variable would help me whenever a page that had this content in it to set the page as loading or to display a message if the page has nothing to show.
UPDATE:
I've managed to create the code I as able to, or had acknowledge to. I'll leave here the code so far:
package com.example.nlsonmartins.myapplication.Highlights;
import java.util.ArrayList;
import org.json.*;
public class HighlightsObjectHandler {
// Constants
private final String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
// Variables
private String
_json;
private Boolean
_updating;
private ArrayList<HighlightObject>
_highlights;
// Properties
public String HighlightsJson() {
return _json;
}
public void HighlightsJson(String highlightsJson) {
// Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
if(highlightsJson != _json && highlightsJson != null) {
_json = highlightsJson;
// Fire the Java equivalent of C# 'OnHighlightsJsonChanged( EventArgs.Empty );'
ParseJson();
}
}
public Boolean HighlightsUpdating() {
return _updating;
}
private void HighlightsUpdating(Boolean isUpdating) {
_updating = isUpdating;
}
public ArrayList<HighlightObject> Highlights() {
return _highlights;
}
// Methods
private void ParseJson() {
try {
JSONObject
jsonObject = new JSONObject(HighlightsJson());
// Fire the Java equivalent of C# 'OnHighlightsContentsChanging( EventArgs.Empty );'
// Parse the JSON object
// Fire the Java equivalent of C# 'OnHighlightsContentsChanged( EventArgs.Empty );'
} catch (JSONException exception) {
}
}
// Events
/* Create the event handler for 'OnHighlightsJsonChanged' */
/* Create the event handler for 'OnHighlightsContentsChanging' and call the 'HighlightsUpdating(true);' method */
/* Create the event handler for 'OnHighlightsContentsChanged' and call the 'HighlightsUpdating(false);' method */
// Constructors
public HighlightsObjectHandler() {
_highlights = new ArrayList<HighlightObject>();
}
}
I don't have an equivalent for the 'JsonObject' type, but other than that I think the following may work for you, using your own custom EventHandler functional interface, custom EventArgs class, and generic 'Event' helper class:
import java.util.*;
public class HighlightsObjectHandler
{
// Constants
private static final String JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Handlers
public Event<CustomEventHandler> HighlightsJsonChanged = new Event<CustomEventHandler>();
public Event<CustomEventHandler> HighlightsContentChanging = new Event<CustomEventHandler>();
public Event<CustomEventHandler> HighlightsContentChanged = new Event<CustomEventHandler>();
// Variables
private String _json;
// Properties
public final String getHighlightsJson()
{
return _json;
}
public final void setHighlightsJson(String value)
{
if (!_json.equals(value) && value != null)
{
_json = value;
OnHighlightsJsonChanged(CustomEventArgs.Empty);
ParseJson();
}
}
private boolean HighlightsUpdating;
public final boolean getHighlightsUpdating()
{
return HighlightsUpdating;
}
private void setHighlightsUpdating(boolean value)
{
HighlightsUpdating = value;
}
private ArrayList<HighlightObject> Highlights;
public final ArrayList<HighlightObject> getHighlights()
{
return Highlights;
}
private void setHighlights(ArrayList<HighlightObject> value)
{
Highlights = value;
}
// Methods
private void ParseJson()
{
//todo: no equivalent to 'JsonObject':
JsonObject jsonObject = null;
//todo: no equivalent to 'out' parameter:
if (JsonObject.TryParse(HighlightsJson, jsonObject))
{
OnHighlightsContentChanging(CustomEventArgs.Empty);
// Json parsing and other stuff...
// ... it shouldn't matter for this question.
OnHighlightsContentChanged(CustomEventArgs.Empty);
}
}
// Events
public final void OnHighlightsJsonChanged(CustomEventArgs eventArgs)
{
if (HighlightsJsonChanged != null)
{
for (CustomEventHandler listener : HighlightsJsonChanged.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
public final void OnHighlightsContentChanging(CustomEventArgs eventArgs)
{
setHighlightsUpdating(true);
if (HighlightsContentChanging != null)
{
for (CustomEventHandler listener : HighlightsContentChanging.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
public final void OnHighlightsContentChanged(CustomEventArgs eventArgs)
{
setHighlightsUpdating(false);
if (HighlightsContentChanged != null)
{
for (CustomEventHandler listener : HighlightsContentChanged.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
// Constructors
public HighlightsObjectHandler()
{
setHighlights(new ArrayList<HighlightObject>());
}
}
#FunctionalInterface
public interface CustomEventHandler
{
void invoke(object sender, CustomEventArgs e);
}
public class CustomEventArgs
{
public static readonly CustomEventArgs Empty;
public CustomEventArgs()
{
}
}
//this is produced as a helper class by C# to Java Converter:
public final class Event<T>
{
private java.util.Map<String, T> namedListeners = new java.util.HashMap<String, T>();
public void addListener(String methodName, T namedEventHandlerMethod)
{
if (!namedListeners.containsKey(methodName))
namedListeners.put(methodName, namedEventHandlerMethod);
}
public void removeListener(String methodName)
{
if (namedListeners.containsKey(methodName))
namedListeners.remove(methodName);
}
private java.util.List<T> anonymousListeners = new java.util.ArrayList<T>();
public void addListener(T unnamedEventHandlerMethod)
{
anonymousListeners.add(unnamedEventHandlerMethod);
}
public java.util.List<T> listeners()
{
java.util.List<T> allListeners = new java.util.ArrayList<T>();
allListeners.addAll(namedListeners.values());
allListeners.addAll(anonymousListeners);
return allListeners;
}
}
import java.util.*;
interface HelloListener
{ void someoneSaidHello();}
NOTE
I'm going to have this StackOverflow answer as a base for what I'm going to explain in this answer.
Okay, so, for what I could read and understand, it isn't that much different building C#-like events in Java ( or, in another point of view, it isn't that hard from someone who develops in C# to build events in Java ).
First, from my perspective, I'd like to point that the way I build the events in Java are almost a copy-paste from C# ( maybe it's the correct way to do it, maybe it isn't ).
Second, I'm going to - hopefully - put this in a way people might understand ( based on tutorials I saw here on StackOverflow and other sites ):
The events on C# are wrapped in a method that is set as internal - usually the OnSomethingChanging or OnSomethingChanged - whereas the Java events are not. Imagine this method in Java:
List<HelloListener> listeners = new ArrayList<HelloListener>();
public void sayHello() {
System.out.println("Hello!!");
// Notify everybody that may be interested.
for (HelloListener hl : listeners)
hl.someoneSaidHello();
}
Now, to make it more C# like, I would to make it like this:
public event EventHandler HelloListener;
public void SayHello() {
Console.WriteLine("Hello!!");
// Notify everybody that may be interested.
if(HelloListener != null) {
HelloListener(this, EventArgs.Empty);
}
}
Basically I was expecting to have to make an OnHelloListener method, then trigger the events on that very method but, on the majority of examples and tutorials that I saw, they would do something like I wrote above. That was what was messing my head really badly ( and probably others too if they come from C# to Java ).
In conclusion
If I was to translate the HighlightsObjectHandler class from C# to Java - and keeping the C# soul in it - I would end with something like this:
public class HighlightsObjectHandler {
// Constants
private final String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
private List<HighlightsListener>
_highlightsListeners = new ArrayList<HighlightsListener>();
// Variables
private String
_json;
private Boolean
_updating;
private List<HighlightObject>
_highlights;
// Properties
public String HighlightsJson() {
return _json;
}
public void HighlightsJson(String highlightsJson) {
// Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
if (!highlightsJson.equals(_json) && highlightsJson != null) {
_json = highlightsJson;
OnHighlightsJsonChanged();
ParseJson();
}
}
public Boolean HighlightsUpdating() {
return _updating;
}
private void HighlightsUpdating(Boolean isUpdating) {
_updating = isUpdating;
}
public List<HighlightObject> Highlights() {
return _highlights;
}
// Methods
private void ParseJson() {
if (HighlightsUpdating()) {
return;
}
try {
OnHighlightsContentsChanging();
// Parse the JSON object
OnHighlightsContentsChanged();
} catch (JSONException exception) {
}
}
// Events
private void OnHighlightsJsonChanged() {
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsJsonChanged();
}
}
private void OnHighlightsContentsChanging() {
HighlightsUpdating(true);
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsContentChanging();
}
}
private void OnHighlightsContentsChanged() {
HighlightsUpdating(false);
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsContentChanged();
}
}
// Constructors
public HighlightsObjectHandler() {
_highlights = new List<HighlightObject>();
}
}
Once again, my problem was basically me expecting to have to create the OnSomethingChanged methods that would trigger the events and not the code directly placed on the methods when I want them to be triggered.
You could say that I was an app that was crashing when you typed this while expecting you to type that.
Java to C#
WARNING If you're easily confused or you're still trying to understand this, I recommend you to not read this part of the answer. This is just an for fun and curiosity block that I found somewhat funny and interesting...
So, let's say that my problem was the opposite that is now, I had a Java class with events and would like to translate it to C#. From what I know to this point I would end with something like this in C#:
public class HighlightsObjectHandler {
// Constants
private const String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
public event EventHandler HighlightsJsonChanged;
public event EventHandler HighlightsContentChanging;
public event EventHandler HighlightsContentChanged;
// Variables
private String
_json;
// Properties
public String HighlightsJson {
get {
return _json;
}
set {
if (value != _json && value != null) {
_json = value;
if (HighlightsJsonChanged != null) {
HighlightsJsonChanged( this, eventArgs );
}
ParseJson();
}
}
}
public Boolean HighlightsUpdating { get; private set; }
public List<HighlightObject> Highlights { get; private set; }
// Methods
private void ParseJson() {
JsonObject
jsonObject;
if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
HighlightsUpdating = true;
if (HighlightsContentChanging != null) {
HighlightsContentChanging( this, eventArgs );
}
// Json parsing
HighlightsUpdating = false;
if (HighlightsContentChanged != null) {
HighlightsContentChanged( this, eventArgs );
}
}
}
// Events
// Constructors
public HighlightsObjectHandler() {
Highlights = new List<HighlightObject>();
}
}
Note how instead the OnHighlightsJsonChanged and the other internal methods are removed and, instead of having the code I had on the methods they are instead where I called the methods.
P.S.: I will mark this answer as the answer to the this question on the next Monday so I can see others answers and select one of them if they fit more as a final answer.

Java: message system needs to be able to pass various objects

I'm writing a messaging system to queue actions for my program to execute. I need to be able to pass various objects by the messages. I currently have a Msg object that accepts (Action enum, Data<?>...object). The Data object is intended to be a wrapper for any object I might pass.
Currently the Data object uses this code, with generics:
public class Data<T> {
private T data;
public Data(T data){
this.data = data;
}
public T getData(){
return data;
}
}
The Msg object takes Data<?>... type, so Msg has a Data<?>[] field.
If getData() is called on a Data<?> object, it returns the Object type. Obviously not ideal.
I need to be able to pass, say, Image objects as well as String objects. I'm certain there's a better way of passing arbitrary data.
The reason you're having trouble is that you're trying to get the static typing system of Java to do something that it can't. Once you convert from a Data<T> to a Data<?>, whatever T was is effectively lost. There's no clean way to get it back.
The quickest way to get it to work (from what you have right now) is to start throwing casts everywhere, like this:
Data<?> d = new Data("Hello");
String contents = (String)d.getData();
This is kind of a terrible idea, so let's go back to the drawing board.
If (ideally), you have all of the types you could ever need ahead of time (i.e. every Data is either a String or an Image or an Integer), then you can pretty easily (though it's a bit tedious) define a Sum type (aka a union if you're coming from C) of the different types of data you'll have to handle. As a class invariant, we assume that exactly one of the fields is non-null, and the rest are null. For this example I'll assume it can be either a String, an Image, or an Integer, but it's fairly simple to add or remove types from Data as necessary.
public class Data {
private Image imgData;
private String stringData;
private Integer intData;
public Data(Image img) {
this.imgData = img;
}
public Data(String stringData) {
this.stringData = stringData;
}
public Data(Integer intData) {
this.intData = intData;
}
public boolean isImage() {
return imageData != null;
}
public boolean isInteger() {
return intData != null;
}
public boolean isString() {
return stringData != null;
}
public Image asImage() {
if(! isImage()) throw new RuntimeException();
return imgData;
}
public Image asString() {
if(! isString()) throw new RuntimeException();
return stringData;
}
public Image asInt() {
if(! isInt()) throw new RuntimeException();
return intData;
}
}
One necessary side effect is that we cannot wrap null without causing exceptional behavior. Is this is desired, it isn't too difficult to modify the class to allow for it.
With this Data class, it's pretty easy to do if-else logic to parse it.
Data d = ....... //Get a data from somewhere
if(d.isImage()) {
Image img = d.asImage();
//...
} else if (d.isString()) {
String string = d.asString();
//...
} else if (d.isInteger()) {
Integer i = d.asInt();
//...
} else {
throw new RuntimeException("Illegal data " + d + " received");
}
If you call getData().getClass() you will get the class or type that was passed, which doesn't seem to me to be the same as an Object. You might not know what you are getting, but you can either find out or define a common interface for everything you might pass. You could for example, call toString() or getClass() on anything passed. Your question is that you are passing any conceivable object, so my question is what are you going to do with it? If you are going to serialize it into a database you don't need know anything about what type it is, otherwise you can test it or call a common interface.
public class PlayData {
class Msg {
private List<Data<?>> message = new ArrayList<Data<?>>();
public void addData(Data<?> datum) { message.add(datum); }
public void printTypes() { for ( Data<?> datum: message ) { System.out.println(datum.getData().getClass()); } }
}
class Data<T> {
private T value;
public Data(T value) { this.value = value; }
public T getData() { return value; }
}
class Listener {
public void receive(Msg msg) { msg.printTypes(); }
}
class Sender {
private Listener listener;
public Sender(Listener listener) { this.listener = listener; }
public void send(Msg msg) { listener.receive(msg); }
}
class MyPacket {
int i;
public MyPacket(int i) { this.i = i; }
}
public static void main(String[] args) throws Exception { new PlayData().run(); }
public void run() throws Exception {
Sender sender = new Sender(new Listener());
Msg msg = new Msg();
msg.addData(new Data<String>("testing") );
msg.addData(new Data<MyPacket>(new MyPacket(42)) );
sender.send(msg);
}
}

Using generics to refactor

I am used to use generics in typed collections, but I never actually used them to develop something.
I have several classes like this:
public class LogInfoWsClient extends GenericWsClient {
public void sendLogInfo(List<LogInfo> logInfoList) {
WebResource ws = super.getWebResource("/services/logInfo");
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<List<LogInfo>>(logInfoList) {
});
}
}
Where the only thing changing between one and another is the service String ("/services/info"), and the type of the list (LogInfo in this case)
I have refactored a couple of methods to a GenericWsClient class, but my objective would be to have something I can use like this:
List<LogInfo> myList = database.getList();
SuperGenericClient<List<LogInfo>> superClient = new SuperGenericClient<List<LogInfo>>();
superClient.send(myList,"/services/logInfo");
But I cannot figure out how to do it, or even if its possible. Would it be possible?
Yes it is possible infact if you look at java.util.collection package for example you will find all classes to be parameterzid.
So your class will be something like this
public SuperGenericClient<E> {
public E getSomething() {
return E;
}
}
Then to use it you will have
SuperGenericClient<String> myGenericClient = new SuperGenericClient<String>();
String something = myGenericClient.getSomething();
Extending your example itself your code will look like this:
public class SuperGenericClient<E> extends GenericWsClient {
public void send(List<E> entityList, String service) {
WebResource ws = super.getWebResource(service);
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<E>(entityList) {
});
}
}
}
public class GenericEntity<E> {
public GenericEntity(List<E> list){
}
}
You must read this for a very good understanding of Generics.
You could write your class like the one below - you can apply the same idea to GenericEntity.
public class SuperGenericClient<T> extends GenericWsClient {
public void send(List<T> list, String service) {
WebResource ws = super.getWebResource(service);
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<T>(list) {
});
}
}
}
You can then call it like that:
List<LogInfo> myList = database.getList();
SuperGenericClient<LogInfo> superClient = new SuperGenericClient<LogInfo>();
superClient.send(myList,"/services/logInfo");
Declare your class like this:
public class LogThing<T> {
public void sendLogInfo(List<T> list) {
// do thing!
}
}
And when you use it, do so like this:
List<LogInfo> myList = db.getList();
LogThing<LogInfo> superClient = new LogThing<LogInfo>();
superClient.sendLogInfo(myList);

Java (Android): calling a function from Context without cast

First off - I'm rather novice at Java so if the question makes no sense do let me know.
Basically I'm making an Android app which communicates with my web service and so I've made a separate class to deal with the communication, which also includes the AsyncTask (I've removed a lot from the code here just for preview):
public class api {
private String caller = null;
Context that = null;
api(Context that) {
this.that = that;
this.caller = that.getClass().getSimpleName();
}
void call(String action) {
/* .... */
}
new back().execute(param1, param2);
}
void callback(String action, String result){
that.callback(action, result);
}
public class back extends AsyncTask<String, Void, String> {
public String response = null;
protected String doInBackground(String... params) {
response = connection.executeRequest(params[1]);
return response;
}
protected void onPostExecute(String result) {
callback("a", "b");
}
}
}
And when I use the class from some part of the app (let's say SomeClass.class), I do:
api WS = new api(this);
WS.call("....");
And it's supposed to execute the function 'callback' which is in SomeClass.
But the key problem here is this line:
that.callback(action, result);
Eclipse makes me add the name of the "caller" class in the cast:
(SomeClass) that.callback(action, result);
But that doesn't work for me, because I use the 'api' class from many different classes, so ideally I need to put a variable in the cast. I do get the name of the "caller" class here:
this.caller = that.getClass().getSimpleName();
//obviously this won't work:
(this.caller) that.callback(action, result);
Is there anyway to do that, or am I doing something fundamentally wrong?
Thank you.
Currently your api class accepts a Context object in its default constructor. It would make more sense to extend Context with a new class which contains a callback method which you can then override in subclasses such as SomeClass, that would negate the need for casting in your api class. e.g:
public class APIContext extends Context
{
public void callback( String action, String result )
{
/* ... */
}
}
public class SomeClass extends APIContext
{
#Override
public void callback( String action, String result )
{
/* ... */
}
}
public class api
{
private APIContext callerContext = null;
public api( APIContext context )
{
this.callerContext = context;
}
public void callback( String action, String result )
{
callerContext.callback( action, result );
}
}

Categories

Resources