Update static object constantly in a thread and using in others activities - java

I have a static object in a class.
public class AppHelper {
public static MyObject CONSTANT_ = new MyObject();
}
// and my object
public class MyObject {
private Integer status;
// get and set for status
}
public class MyActivity extends Activity {
// oncreate()
// onresume()
public void OnUpdate() {
if (AppHelper.CONSTANT_.getStatus == 1) {
// doStuff
} else if (AppHelper.CONSTANT_.getStatus == 2) {
// doOtherStuff
}
}
}
public class MyService extends Service {
// oncreate()
public void callServer() {
// implementation of thread ommited
Endpoint.get(URL, new CallBack(Response response) {
AppHelper.CONSTANT_ = jsonToObj(reponse); // method for conversion is Ok
});
}
}
And activities have to call AppHelper.CONSTANT_.getStatus() for show a different view. My thread updates CONSTANT_ object constantly.
So, sometimes I use something like this:
MyObject obj = AppHelper.CONSTANT_;
When I set any field in obj, few seconds later the setted field come back to empty. Is obj linked with AppHelper.CONSTANT_ ? If so, have some other way to supply this status field without have a constant?

Related

Initializing a boolean to use in every api call

I have a service shown below
public interface SomeService{
#GetMapping("/someapi")
public Object getData();
}
i have impl class shown below
public class ServiceImpl{
private boolen isSomeCondition;
public Object getData(){
callSomeMethod();
if(isSomeCondition)
//do something
else
//do some other
}
public void callSomeMethod(){
if(someCondition)
//do something
else
//set isSomeCondition to true
isSomeCondition=true;
}
i want this isSomeCondition to be set to false initially for every call to the "/someapi" and later to be changed when callSomeMethod is executed. whatever i have above doesn't seem to work as global variable isSomeCondition is stateless bean.
what could be alternatives to this?
If you require state, then introduce state. Create a stateful object for each request:
public class ServiceImpl{
public Object getData(){
final DataGetter getter = new DataGetter();
return getter.getData();
}
static class DataGetter {
private boolen isSomeCondition;
public Object getData(){
callSomeMethod();
if(isSomeCondition) {
//do something
} else {
//do some other
}
}
public void callSomeMethod(){
if(someCondition) {
//do something
} else {
//set isSomeCondition to true
isSomeCondition=true;
}
}
}
}
Since you are using Spring, changing the bean scope might be an option too:
#RequestScope
public class ServiceImpl {
// ...
}
Try something like below. Instead of having isSomeCondition as global variable have it as local variable and pass it to the method.
public class ServiceImpl{
public Object getData(){
private boolen isSomeCondition;
isSomeCondition = callSomeMethod(isSomeCondition);
if(isSomeCondition)
//do something
else
//do some other
}
Here based on your condition you can set it and return.
public boolean callSomeMethod(){
if(someCondition)
//do something
else
//set isSomeCondition to true
isSomeCondition=true;
return isSomeCondition;
}

Null pointer exception from List in constructor parameter

I'm creating a class that has a List of objects as a constructor parameter, but I'll getting a null pointer exception when I try to use the initialized List. My class
public class ControlUnit {
private List<Sensor> sensors;
public void constructor(List<Sensor> sensorList) {
sensors = sensorList;
}
public void pollSensors() {
for (Sensor sensor : sensors) {
System.out.println("do something");
}
}
}
used like this:
List<Sensor> sensors = new ArrayList<Sensor>();
sensors.add(new FireSensor());
sensors.add(new SmokeSensor());
ControlUnit unit = new ControlUnit();
unit.pollSensors();
and I'm getting the error
java.lang.NullPointerException
at ControlUnit.pollSensors(ControlUnit.java:15)
What am I missing in my constructor?
The constructor is defined completely wrong. Check the following code snippet.
public class ControlUnit {
private List<Sensor> sensors;
public ControlUnit(List<Sensor> sensorList) {
sensors = sensorList;
}
public void pollSensors() {
for (Sensor sensor : sensors) {
System.out.println("do something");
}
}
}
And use it like this.
List<Sensor> sensors = new ArrayList<Sensor>();
sensors.add(new FireSensor());
sensors.add(new SmokeSensor());
ControlUnit unit = new ControlUnit(sensors);
unit.pollSensors();
public void constructor(List<Sensor> sensorList) {
This is not a constructor declaration. You need
public ControlUnit(List<Sensor> sensorList) {
and then call it with the list you want to use.
You're constructing your class wrongly.
A constructor in Java takes the form of a method with the name of the class and without any return type:
public ControlUnit(List<Sensor> sensorList) { ... }
You need to pass the list to the object when creating an instance of it as a parameter so like this: ControlUnit unit = new ControlUnit(sensors); and also change the constructor method to
public ControlUnit(List<Sensor> sensorList) {
sensors = sensorList;
}
For your class ControlUnit you have not got a constructor, so the Idea which you use will generate an empty constructor for your class that you call when you initialize your ControlUnit object here: ControlUnit unit = new ControlUnit()
So you will not initialize your List<Sensor> sensors list and you will not be able to iterate through it because it is pointing to null.
In order to do it properly, you have to write your constructor in the right way like this:
public class ControlUnit {
private List<Sensor> sensors;
public void pollSensors() {
for (Sensor sensor : sensors) {
System.out.println("do something");
}
}
public void ControlUnit (List<Sensor> sensorList) {
sensors = sensorList;
}
}
Your constructor method has to be the same name as your class.
When you call new ControlUnit(), you will call that constructor. But in this case, you have a parameter there, so we have to pass it at the calling like this: ControlUnit unit = new ControlUnit(sensors);
So when the constructor will run, it will assign the value to your list, so you can iterate through it.

Is my method to update textview from a volley response the 'Android way' the right way?

I have a fragment that sets the textViews from a data object. This data object is initially null when the fragment is created but gets updated after a network request. Now to update the textviews I create a function 'updateAll' and pass the fragment to the callback function that handles the network response. And once the data is set to the data object I call 'updateAll' from the fragment reference.
Example :
class someFragment extends Fragment {
private Textview foo;
private dataObject obj;
...
public onCreate(...) {
this.obj = new dataObject();
sendRequestToVolley(..., new VolleyCallbacks(this));
}
public onCreateView(...) {
...
foo.setText(obj.someVar);
}
public void updateAll() {
foo.setText(obj.someVar);
}
}
class VolleyCallbacks implements someInterface {
public VolleyCallbacks(someFragmment fragment, dataObject obj) {
this.obj = obj;
this.fragment = fragment;
}
public onSuccess(Response r) {
obj.updateData(r);
this.fragment.updateAll();
}
}
Is this the correct way to do this? Is there a better method?
You code looks mainly good. I see one issue: you're keeping the Fragment as a strong reference. It can generate a memory leak if the fragment is destroyed (ie. the user presses back) before the network call is completed. To prevent that, you should use a WeakReference.
I also wouldn't modify your data object inside the callback class. It's better to let the fragment modify it since he is the one holding the reference to it.
I would transform your code like that:
public class SomeFragment extends Fragment {
private Textview foo;
private dataObject obj;
...
public onCreate(...) {
this.obj = new dataObject();
sendRequestToVolley(..., new VolleyCallbacks(this));
}
public onCreateView(...) {
...
refreshTextView();
}
private void refreshTextView() {
foo.setText(obj.someVar);
}
void onRequestSuccess(Response r) {
obj.updateData(r);
refreshTextView();
}
}
class VolleyCallbacks implements SomeInterface {
private WeakReference<SomeFragment> fragmentWeak;
public VolleyCallbacks(SomeFragment fragment) {
this.fragmentWeak = new WeakReference<>(fragment);
}
public onSuccess(Response r) {
SomeFragment fragment = this.fragmentWeak.get();
if (fragment != null) {
fragment.onRequestSuccess(r);
}
}
}

How to handle return value from AsyncTask

I am using AsyncTask class with the following signature:
public class ApiAccess extends AsyncTask<List<NameValuePair>, Integer, String> {
...
private String POST(List<NameValuePair>[] nameValuePairs){
...
return response;
}
}
protected String doInBackground(List<NameValuePair>... nameValuePairs) {
return POST(params);
}
I am trying to call it from other class through:
ApiAccess apiObj = new ApiAccess (0, "/User");
// String signupResponse = apiObj.execute(nameValuePairs);
String serverResponse = apiObj.execute(nameValuePairs); //ERROR
But here I get this error:
Type mismatch: cannot convert from AsyncTask<List<NameValuePair>,Integer,String> to String
Why is that when i have specified String as the third parameter in Class extension line?
You can get the result by calling AsyhncTask's get() method on the returned AsyncTask, but it will turn it from an asynchronous task into a synchronous task as it waits to get the result.
String serverResponse = apiObj.execute(nameValuePairs).get();
Since you have your AsyncTask in a seperate class, you can create an interface class and declare it in the AsyncTask and implement your new interface class as delegate in the class you wish to access the results from. A good guide is here: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?.
I will attempt to apply the above link to your context.
(IApiAccessResponse)
public interface IApiAccessResponse {
void postResult(String asyncresult);
}
(ApiAccess)
public class ApiAccess extends AsyncTask<List<NameValuePair>, Integer, String> {
...
public IApiAccessResponse delegate=null;
protected String doInBackground(List<NameValuePair>... nameValuePairs) {
//do all your background manipulation and return a String response
return response
}
#Override
protected void onPostExecute(String result) {
if(delegate!=null)
{
delegate.postResult(result);
}
else
{
Log.e("ApiAccess", "You have not assigned IApiAccessResponse delegate");
}
}
}
(Your main class, which implements IApiAccessResponse)
ApiAccess apiObj = new ApiAccess (0, "/User");
//Assign the AsyncTask's delegate to your class's context (this links your asynctask and this class together)
apiObj.delegate = this;
apiObj.execute(nameValuePairs); //ERROR
//this method has to be implement so that the results can be called to this class
void postResult(String asyncresult){
//This method will get call as soon as your AsyncTask is complete. asyncresult will be your result.
}
I would suggest implementing a Handler Callback. You would pass the fragment's (or activity's) Handler to the AsyncTask, which the AsyncTask will call when it is finished. The AsyncTask can also pass back an arbitrary object.
Here is an example AsyncTask, which I have in its own file (not subclassed):
public class MyTask extends AsyncTask<Void, String, String> {
private static final String TAG = "MyTask";
private Handler mCallersHandler;
private Candy mObject1;
private Popsicle mObject2;
// Return codes
public static final int MSG_FINISHED = 1001;
public SaveVideoTask(Handler handler, Candy candyCane, Popsicle grapePop ) {
this.mCallersHandler = handler;
this.mObject1 = candyCane;
this.mObject2 = grapePop;
}
#Override
protected String doInBackground(Void... params) {
// Do all of the processing that you want to do...
// You already have the private fields because of the constructor
// so you can use mObject1 and mObject2
Dessert objectToReturn = mObject1 + mObject2;
// Tell the handler (usually from the calling thread) that we are finished,
// returning an object with the message
mCallersHandler.sendMessage( Message.obtain( mCallersHandler, MSG_FINISHED, objectToReturn ) );
return (null);
}
}
This example assumes that your AsyncTask needs a piece of Candy and a Popsicle. Then it will return a Dessert to your fragment.
You can construct and run the AsyncTask in one line from your fragment with:
( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute();
But of course, you will first need to set up the fragment's handler (myFragmentHandler). To do this, your fragment (or activity) should look like (NOTE the "implements Handler.Callback"):
public class MyFragment extends Fragment implements Handler.Callback {
private Handler mFragmentHandler;
private Candy candyCane;
private Popsicle grapePop;
#Override
public void onCreate(Bundle savedInstanceState) {
// Standard creation code
super.onCreate(savedInstanceState);
setRetainInstance(true);
// Create a handler for this fragment
mFragmentHandler = new Handler(this);
// Other stuff...
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
// Inflate the layout
View v = inflater.inflate(R.layout.my_fragment_layout, parent, false );
// The candyCane and grapePop don't need to be set up here, but
// they MUST be set up before the button is pressed.
// Here would be a good place to at least initialize them...
// Perhaps you have a button in "my_fragment_layout" that triggers the AsyncTask...
Button mButton = (Button) v.findViewById(R.id.mButton);
mButton.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute();
}
});
return v;
}
#SuppressWarnings("unchecked")
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MyTask.MSG_FINISHED:
// Let's see what we are having for dessert
Dessert myDessert = (Dessert) msg.obj;
break;
}
return false;
}
}
If you use these pieces of code, a button press will trigger the AsyncTask. The calling fragment will continue to execute while the AsyncTask is processing. Then, when the AsyncTask is finished, it will send a message to the fragment saying that it is finished, and pass an object with the message. At this point, the fragment will see the message, and do whatever you want.
Note: There might be typos. This is cut from a very large and complicated code.
The problem is that when you call execute, the AsyncTask object is returned, but not the result yet. The result is computed in the background. The type of the result will eventually be a String (as you specified), and will be passed to onPostExecute().
You should use the AsyncTask as follows:
public class ApiAccess extends AsyncTask<List<NameValuePair>, Integer, String> {
...
private String POST(List<NameValuePair>[] nameValuePairs){
...
return response;
}
protected void onPreExecute (){
// this is run on the main (UI) thread, before doInBackground starts
}
protected void onPostExecute (String result){
// this is run on the main (UI) thread, after doInBackground returns
}
protected String doInBackground(List<NameValuePair>... nameValuePairs) {
// run in another, background thread
return POST(params);
}
}
Note that in your example you are not returning the result in doInBackground(), which you should.
Please read AsyncTask. You can get result on onPostExecute method. You can't do something like :
String serverResponse = apiObj.execute(nameValuePairs);
because it is async.

Pass outer anon class ref to a method in an inner anon class

How to pass outer anon class ref to a method in an inner anon class in Java?
I have a method that makes async call to a server - sendCall(some_args, callback). The callback is represented by anonymous class (let's name it OuterAnon) and contains a method for failure case. Inside this method a message box is created and sendCall() is called each time OK button is pressed. So I need to pass OuterAnon to the method again.
Here is a code to demonstrate what I mean:
private void sendCall(MyData data, OuterAnon<Boolean> callback){/*...*/}
private void myCall(final MyData data) {
sendCall(data, new OuterAnon<Boolean>() {
public void onFailure(Throwable throwable) {
final OuterAnon<Boolean> callback = this; //how to avoid this?
MessageBox.show(throwable.getMessage(), new MessageListener() {
public void process(MessageBox.OnClick action) {
if (action == MessageBox.OnClick.OK) {
sendCall(new MyData("resend?"), callback);
}
}
});
}
}
});
}
As you noticed, I take a ref for callback here:
final OuterAnon<Boolean> callback = this;
and use it here:
sendCall(new MyData("resend?"), callback);
But I want to avoid ref creation and pass callback like:
sendCall(new MyData("resend?"), this); //at the moment we point to MessageListener instead of OuterAnon.
Is there any way to do it in Java?
It's hard for us to fix since you've only shown incomplete code with classes that aren't supplied, so I don't know if this example is syntactically correct. That being said, a refactoring like this may suit your needs:
private void myCall(final MyData data)
{
sendCall(data, new OuterAnon<Boolean>()
{
public void onFailure(Throwable throwable)
{
showErrorMessage(throwable);
}
});
}
private void showErrorMessage(Throwable throwable)
{
MessageBox.show(throwable.getMessage(), new MessageListener()
{
public void process(MessageBox.OnClick action)
{
if (action == MessageBox.OnClick.OK)
{
sendCall(new MyData("resend?"));
}
}
});
}
private void sendCall(MyData data)
{
sendCall(data, this);
}
In general, I think it's a usually good idea to abstract code out of anon inner classes and into their own method on the enclosing class. It's now testable, reusable, and more readable, IMO.
If you really need to specify the onFailure inside the inner class the way you showed the code, and if you need to use that specific reference for callback, and you need to code this way...
Let's answer the question: no.
In my attempts, I've achieved 3 ways to access the anon-inner-least instance inside the anon-inner-most instance, but I think that none satisfies what you expect.
In that case, the anon-inner-most doesn't have a reference to the anon-inner-least: as you said, the this now points to the anon-inner-least.
Also, I tried to search at the java specification, but couldn't find exactly the answer to the question - if someone find the answer there, please contribute.
My try:
import java.util.ArrayList;
import java.util.LinkedList;
public abstract class AnonTest {
public static void main(String[] args) {
new ArrayList<Object>() {
private static final long serialVersionUID = -5986194903357006553L;
{
// initialize inner anon class
add("1");
}
// Way 1
private Object thisReference1 = this;
// Way 2
private Object getThisReference2() {
return this;
}
#Override
public boolean equals(Object obj) {
// Way 3
final Object thisReference3 = this;
new LinkedList<Object>() {
private static final long serialVersionUID = 900418265794508265L;
{
// initialize inner inner anon class
add("2");
}
#Override
public boolean equals(Object innerObj) {
// achieving the instance
System.out.println(thisReference1);
System.out.println(getThisReference2());
System.out.println(thisReference3);
System.out.println(this);
System.out.println();
// achieving the class
System.out.println(thisReference1.getClass());
System.out.println(getThisReference2().getClass());
System.out.println(thisReference3.getClass());
System.out.println(this.getClass());
System.out.println(this.getClass().getEnclosingClass());
return super.equals(innerObj);
}
}.equals("");
return super.equals(obj);
}
}.equals("");
}
}

Categories