Activity collides with AsyncTask? How to implement AsyncTask into GUI? - java

I am sorry for my bad english skills. I'm new to programming/stackoverflow and try to create a little android quiz app. This app has to connect to a php server and login/getquestion...
The simplest example is the login. The user has to type in his data and then i have to connect.
To provide that the Gui doesnt freeze i have to use asynchronous tasks.
Here the activity's code:
public void login(final String username, final String password) {
final Activity a = this;
FutureTask t = new FutureTask(new Callable() {
public Object call() {
Connection.GetInstance(a).login(username,password);
afterLoginTry(username,password);
return null;
}
});
t.run();
}
This calls a method in another class, which calls another FutureTask which calls an AsyncTask. At the end there is always an public synchronized method such as afterlogintry(). This works but it's a bit slow and i think dirty code.
My main problem is that i don't know how to give results back through different layers of classes and especially to the activity without using hotfixes all the time.
Is there any good explanation or tutorial, which describes how to design such a construct?
Thx for help

The way you can pass AsyncTask results back to other classes, is by declaring callbacks for the task, that will then report the result to a listener. Here is how it works.
First, you must declare an interface in your AsyncTask which contains a method that will send out the result of the task. So in my example task below, my result is a String. The String gets passed to onPostExecute() when the task finishes its work. I then call my callback method on a registered listener, and pass that return value on to whoever is listening for it. You register a listener by passing in an instance of your callbacks from whichever class is creating the task.
public class MyTask extends AsyncTask<String, Void, String> {
MyTaskCallback listener;
public MyTask(MyTaskCallback listener) {
this.listener = listener;
}
protected String doInBackground(String... params) {
String input = params[0];
//do work
input += "did some work on this String";
return input;
}
//When the thread finishes its work, this gets
//called on the main UI thread
protected void onPostExecute(String result) {
listener.onResultReceived(result);
}
public interface MyTaskCallback {
void onResultReceived(String result);
}
}
So next we need to register a listener for these callbacks, so when the result comes in from the task, it will get reported directly to our class. So let's say we have a simple Activity. The way we register the callbacks is to use the implements keyword on our class declaration, and then to actually implement the callback method in the class itself. We then create our task, and we pass in this which is our Activity that implements the callbacks. A simple example Activity that does this looks like this:
public class TaskActivity extends AppCompatActivity implements MyTask.MyTaskCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
//we pass in "this" because our Activity itself
//implements the callbacks below.
MyTask myTask = new MyTask(this);
myTask.execute();
}
//Here we implement our callback method, so the task
//can send its results straight through here
public void onResultReceived(String theResult) {
Log.d("TASK RESULT", "Here is our result String: "+theResult);
}
}
Now, our task has our Activity connected to it, through the callbacks we passed into it. So now when our task gets a result, we can send it directly to our listener, which is our Activity, and the result will come right through to our implemented onResultReceived method.
Callbacks are a great way to pass information around between classes while also keeping everything very separated. Hope this helps!

Related

Best practices for start() and stop() in Android MVP?

I have some questions regarding the Presenter’s start(), stop() method. What would you normally put into these methods to prevent memory leaks or any potential problem.
For example, I have an Activity that host a VideoView. The videoPath passed to the Activity will be passed to the Presenter to a VideoUtility to trim the original video into a shorter one before getting passed back to the Activity to be played with the VideoView.
Here’s the confusion: I don’t know where is the appropriate place to call the trimVideo() method as it essentially only need to happen once (unlike in the Android Architect Blueprint, the task is updated with latest data, and thus it’s put in the onResume()).
Please see the code snippet below:
VideoEditorContract:
public interface VideoEditorContract {
interface View extends BaseView<Presenter> {
void playTrimVideo(String trimmedVideoPath);
}
interface Presenter extends BasePresenter {
}
}
VideoEditorActivityBase:
public class VideoEditorActivityBase extends AppCompatActivity implements VideoEditorContract.View {
private VideoEditorContract.Presenter mPresenter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_editor);
String videoPath = getIntent().getStringExtra(RequestCode.EXTRA_VIDEO_PATH);
mPresenter = new VideoEditorPresenter(videoPath, this);
}
#Override
public void onResume(){
super.onResume();
mPresenter.start();
}
#Override
public void playTrimVideo(String trimmedVideoPath) {
final VideoView vv = findViewById(R.id.act_video_editor_videoView);
vv.setVideoPath(trimmedVideoPath);
vv.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
vv.start();
}
});
}
#Override
public void setPresenter(VideoEditorContract.Presenter presenter) {
//do nothing as this activity has already init a presenter
}
}
VideoEditorPresenter:
public class VideoEditorPresenter implements VideoEditorContract.Presenter {
private final VideoEditorContract.View mVideoEditorView;
#NonNull
private String mVideoPath;
public VideoEditorPresenter(#NonNull String videoPath, #NonNull VideoEditorContract.View videoEditorView) {
mVideoPath = checkNotNull(videoPath);
mVideoEditorView = checkNotNull(videoEditorView, "videoEditorView cannot be null!");
mVideoEditorView.setPresenter(this);
//trimVideo(); //should I do it here since this task is only need to be done once
}
#Override
public void start() {
//trimVideo(); //I can do it here but then I need to introduce a control variable; not sure if this is the best practice
}
private void trimVideo() {
//trim video stuff
}
// Currently it doesn't have a stop() method. But if it have one,
// what should I put in it? Releasing and clean up the
// VideoUtility I suppose?
}
I got the answer from Francesco Cervone in Medium about this matter (his article is also an excellent resource on MVP, btw. Very well in tune with the Android Architect Blueprint). I leave the relevant bit here for future reader.
Hi, thank you.
Well, I think that the video should be trimmed in the Presenter#start(). Then, after the video has been trimmed, the presenter should call view.playTrimmedVideo(). You shouldn’t do anything in the presenter constructor.
I suppose the video “editing” is something expensive, so you should do that in a separate thread (using for example an async task). You need to implement the Presenter#stop() method because you have to cancel ongoing operations if there are any, unless you retain the presenter.
You said that the trimVideo should be called just once. You could cache/persist in some way the result of trimVideo so that if the video has been already trimmed, you use it.
I hope I answered your question.
"Could you elaborate more on why shouldn’t we put anything in the Presenter’s constructor? I’ve seen the Presenter’s bare minimal constructor in a couple of places but I don’t understand the reason behind it."
First, it’s a responsibility problem: you are going to create an instance of Presenter, and I don’t think that the video editing is something that belongs to the construction of that object.
Second, you don’t know when the presenter is being instantiated, so you shouldn’t execute expensive tasks in the constructor. If you use some dependency injection framework, the construction of the Presenter would be managed by the framework itself and it needs to be efficient. The construction of other objects could depend on the presenter one.

Is it possible to call doInBackground from onPostExecute?

#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
asyntask.execute();
}
I'm reading data from some API. Is it possible to call doInBackground() from onPostExecute?
I want do it recursively like (network task and update in UI ) for 5 times. Thanks in advance.
Starting the AsyncTask again from inside onPostExecute is a horrible idea. As you want to do it recursively like 5 times for network calls along with UI update, I would like to suggest you to keep an interface to keep track of the AsyncTask call.
So here's an example about how you can achieve the behaviour. You may create an interface like this.
public interface MyResponseListener {
void myResponseReceiver(String result);
}
Now you declare the interface in your AsyncTask class too. So your AsyncTask may look like this.
public class YourAsyncTask extends AsyncTask<Void, Void, String> {
// Declare an interface
public MyResponseListener myResponse;
// Now in your onPostExecute
#Override
protected void onPostExecute(final String result) {
// Send something back to the calling Activity like this to let it know the AsyncTask has finished.
myResponse.myResponseReceiver(result);
}
}
Now you need to implement the interface you've created already in your Activity like this. You need to pass the reference of the interface to the AsyncTask you're starting from your Activity
public class MainActivity extends Activity implements MyResponseListener {
// Your onCreate and other function goes here
// Declare an AsyncTask variable first
private YourAsyncTask mYourAsyncTask;
// Here's a function to start the AsyncTask
private startAsyncTask(){
mYourAsyncTask.myResponse = this;
// Now start the AsyncTask
mYourAsyncTask.execute();
}
// You need to implement the function of your interface
#Override
public void myResponseReceiver(String result) {
if(!result.equals("5")) {
// You need to keep track here how many times the AsyncTask has been executed.
startAsyncTask();
}
}
}
doInBackground() is called before calling onPostExecute.
Since you cannot perform network tasks on the UI thread, an AsyncTask is created.
The AsyncTask executes in the background, performing the network task on the worker thread. Then after the background task is completed, onPostExecute() is called that makes the UI changes on the UI thread.
This should help : https://developer.android.com/reference/android/os/AsyncTask.html
https://developer.android.com/training/basics/network-ops/index.html
The AsyncTask class is used to do some work in background and publish the results to the MainThread so it's generally not possible because the work that's being done in the worker thread may not be doable in MainThread, (like the NetworkOnMainThreadException when you do networking in MainThread).
I suggest you to make an array of your jobs and call the execute() method of your subclass of AsyncTask and it will serialize the jobs to be done in a worker thread.

Best way to get result from an AsyncTask to the caller class

I have implemented a way of getting the result from onPostExecute back to my main activity. I wanted to know if this is the right thing I did, is there any more chance of improving it, and if it's not the best way, what is the best way?
This is what I have done:
public class MainClass implements AsyncResponse {
private MyAsyncTask asyncTask;
public MainClass() {
asyncTask = new MyAsyncTask();
asyncTask.asyncResponse = this;
}
public void startTask( {
asyncTask.execute("string");
}
#Override
public void processDone(String res) {
// got response in MainClass from onPostExecute
}
private class MyAsyncTask extends AsyncTask<String, String, String> {
protected AsyncResponse asyncResponse = null;
#Override
protected String doInBackground(String... urls) {
return "some processed string";
}
#Override
protected void onPostExecute(String res) {
this.asyncResponse.processDone(res);
}
}
}
Here's the AsyncResponse interface:
public interface AsyncResponse {
void processDone(String res);
}
I want to know in terms of processing speed that on an average android mobile device, would this be a good approach and if not, how do I improve it to make it a good approach?
Thanks.
I always done this way and never had any issues. I would say it is the best way.
in one Line without any callback
String s= new MyAsyncTask().execute().get();
You added an unnecessary interface - and perhaps it makes your code less usable.
First, if you create the AsyncTask as a class within your Activity there is no need for the interface. You can simply do this:
#Override
protected void onPostExecute(String res) {
processDone(res);
}
The AsyncTask will execute onPostExecute on the UI thread and you can call the Activity method without the interface.
Second, if you create AsyncTask outside the Activity class (for example, in its own java file) then you can use this method, except it is not a good idea because it will hold a reference to the Activity on another thread - it's a memory leak risk.
To avoid that, your interface should be implemented in a separate class, like AsyncTaskResponse.java that is passed to the AsyncTask class.
Last, AsyncTask provides the response in the form of a String if that is sufficient. You should look at the docs on AsyncTask:
https://developer.android.com/reference/android/os/AsyncTask.html
You are wrapping the AsyncTask inside another POJO class; doing this doesn't hurt, but provides little benefit.
Consider that when the task is completed, you will want a callback notification somewhere. Your MainClass will get a callback in processDone(), but something will need to be listening to MainClass to get that notification.
Here is a pattern I always use with my AsyncTask subclasses:
public class GetDataRemoteTask extends AsyncTask<String, Void, Data> {
private static final String TAG = "GetDataRemoteTask ";
private WeakReference<GetDataResultListener> mListenerRef;
private Exception mExc;
#Override
protected Data doInBackground(String... params) {
Data result = null;
try {
result = mService.getData(params[0], params[1], params[2]);
} catch (Exception e) {
Log.e(TAG, "Error occurred getting data", e);
mExc = e;
}
return result;
}
#Override
protected void onPostExecute(Data result) {
if (mListenerRef != null) {
GetDataResultListener listener = mListenerRef.get();
if (listener != null) {
if (mExc == null) {
listener.dataReceived(result);
} else {
listener.dataException(mExc);
}
}
}
}
public void setGetDataResultListener(GetDataResultListener listener) {
if (listener == null) {
this.mListenerRef = null;
} else {
this.mListenerRef = new WeakReference<GetDataResultListener >(listener);
}
}
public static interface GetDataResultListener {
public void dataReceived(Data data);
public void dataException(Exception exc);
}
}
So to start off, here I have an interface, like you do, for connecting to the AsyncTask. But I don't wrap my AsyncTask with an implementation, I expect that I will have an Activity or a Fragment that will implement this interface. (That's why I use a WeakReference; if the Activity finishes, my AsyncTask won't keep holding on to the Activity. But that also means I can't use an anonymous class listener unless the client holds the reference for it.)
My client code will look like this:
GetDataRemoteTask task = new GetDataRemoteTask();
task.setListener(this);
task.execute(param1, param2, param3);
I also have a way to find out if there was an exception that occurred in the background task. Any background exceptions should always be reported to the client, which can decide how best to deal with the exception - for example pop up a dialog for the user, so they know the request failed.
I think that a big drawback of AsyncTask is that it doesn't have more structure around handling exceptions that occur in the background thread.
My task holds a reference to the exception, but I have also used Pair<Data, Exception> as a type parameter for return result so I don't need the exception property.
Using this pattern has helped me avoid some typical problems that occur when coding AsyncTask subclasses.

android waiting for response from server

say I want to perform an Http request from the server, this process takes time.
now because of this, the http request needs to be run on a different thread (AsyncTask, Runnable, etc.)
but sometimes I just need the response when I ask for it, in order to update the UI
using Thread.sleep in a loop to wait for the response is not good performance wise
example: I want the user's name, I ask the server for it, and I have to wait for it
now the activity calls the UserManager that calls the serverHandler that performs the operation and returns the result back
maybe an event system is in order, but I'm not sure how to do this in my scenerio
and quite frankly I am really confused on this issue
please help someone?
This can most definitely be done w/ AsyncTask... Handle the network request in doInBackground() and once doInBackground() is finished, onPostExecute() is triggered on the UI thread and that's where you can execute any code that will update UI elements.
If you need something a bit more generic and re-usable, you would probably want to implement a callback... I'll refer to the UI thread as the client and the AsyncTask as the server.
Create a new interface and create some method stubs.
public interface MyEventListener {
public void onEventCompleted();
public void onEventFailed();
}
Have your client pass instance of MyEventListener to the server. A typical way of doing this is to have your client implement the interface (MyEventListener) and pass itself to the server.
public class MyActivity implement MyEventListener {
public void startEvent() {
new MyAsyncTask(this).execute();
}
#Override
public void onEventCompleted() {
// TODO
}
#Override
public void onEventFailed() {
// TODO
}
}
On the onPostExecute of the server, check if the callback is null and call the appropriate method.
public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
private MyEventListener callback;
public MyAsyncTask(MyEventListener cb) {
callback = cb;
}
[...]
#Override
protected void onPostExecute(Void aVoid) {
if(callback != null) {
callback.onEventCompleted();
}
}
}
You can read more about callbacks here: http://www.javaworld.com/javaworld/javatips/jw-javatip10.html

Own Listener change UI-Thread in Android

#first Sorry for my bad english.
I have created a own Listener. I want to change a TextView, when the Listener is called in the MainActivity from a Service. The idea for my own Listener is from:
http://tseng-blog.nge-web.net/blog/2009/02/17/how-implement-your-own-listener-android-java/
In the Code Example the TriggerMethod() ist called from a Calculation Thread, running in the Service.
I solved the Problem, but I find, it isn't pretty nice, because in every new Activity I have to make a new Thread. Is it possible to create an interface/listener that automatically can change the UI?
Used to solve the Problem:
http://developer.android.com/guide/components/processes-and-threads.html
ResultListener.java:
public interface ResultListener {
public void onResultAvailable(double result);
}
SimuService.java:
public class SimuService extends Service {
private ResultListener mResultListener = null;
public void setResultListener(ResultListener listener){
mResultListener=listener;
}
public void triggerMethode(){
observeResultDouble=getObserveDouble;
mResultListener.onResultAvailable(observeResultDouble);
}
MainActivity:
public class MainActivity extends FragmentActivity{
TextView txtView;
ResultListener mResultListener;
SimuService mSimuService;
protected void onCreate(Bundle savedInstanceState) {
txtView = (TextView) findViewById(R.id.txtServiceTime);
//Create Service .....an Bind
mResultListener = new ResultListener() {
#Override
public void onResultAvailable(double result) {
txtView.setText("Result: "+result);
}
};
mSimuService.setResultListener(mResultListener);
}
MY SOLUTION:
ResultListener = new ResultListener() {
#Override
public void onResultAvailable(double result) {
this.result=result;
runOnUiThread(setNewDataToUI);
}
};
private Thread setNewDataToUI = new Thread(new Runnable() {
#Override
public void run() {
txtView.setText("Result: "+result);
}
});
First of all: If you reference a Service in an Activity, the Service becomes pretty much useless. The advantage of services are, that they are loose coupled and can work indepenendtly form activities (=what the user sees) and its lifecycle and might even be in their own process. Thus activity-service communication is through intents or inter-process language AIDL, not through callbacks. If you want something executed asynchronosly use AsyncTask.
To your main problem: as you found out, you can only modify the UI on the UI-thread. So by design, leave changing UI in the component, thats responsibly for that (either activtiy or fragment), that will prevent the need of runOnUiThread()
Your code seems like txtView.setText("Result: "+result); will be executed in the Activity, but it wont. It will be executed in the Service, which (as I impleied before) does not run on the UI-thread. The problem is, I dont get the intent, what exactly you want to achieve so it is hard to give you an alternative solution.

Categories