How One Interface Can Be Used for Different Background Android Tasks

How one interface can be used for different background android tasks?

The most simplistic solution I can think of is to modify your DelegateTaskCompleted interface so as it looks like this:

public interface DelegateTaskCompleted{
public void JsonArrayLoaded(AsyncTask<String, String, String> task,
JSONArray result);
}

Then your onPostExecute will send itself back like below:

protected void onPostExecute(String file_url)   
{
pDialog.dismiss();
delegate.JsonArrayLoaded(this, gotNearestbeacons);
}

Finally, in your MainClass, you can have a conditional check based on the type of AsyncTask:

 @Override
public void JsonArrayLoaded(AsyncTask<String, String, String> task,
JSONArray result)
{
if(task instanceof GettingBeaconsList) {
// do stuff related to the beacon list
}

else if(task instanceof GettingAirports) {
// do airport list stuff
}

}

That way you can easily identify the AsyncTask that sends through the response without having to track which it is, if one takes longer than the other etc.


Alternatively, have another class that extends AsyncTask but adds an abstract variable for identification.

public class TrackableAsyncTask extends AsyncTask<String, String, String>{
public abstract int getId();

public static final int ID_AIRPORT = 1;
public static final int ID_BEACONS = 2;
... etc
}

Then have your Airport and Beacon AsycTasks extend this instead. This will require them to implement the getId method.

public class GettingAirports extends AsyncTask<String, String, String> {
public int getId(){
return ID_AIRPORT;
}
}

And then instead of doing a conditional if (task instanceof GettingAirports) you can do a switch statement like below:

switch(task.getId()){
case TrackableAsyncTask.ID_AIRPORT:
// run airport code
}

Hope this helps.

How one interface can be used for more than two background android tasks within one activity?

enum BackgroundType{ GET, POST }

public interface onBackgroundTaskListener<T> {
void onTaskComplete(T result, BackgroundType type);
}

--------------------------
BackgroundTask bt1 = new BackgroundTask(this, ApiHelper.GET, GET);
bt.execute(url1);

BackgroundTask bt2 = new BackgroundTask(this, ApiHelper.POST, params, POST);
bt.execute(url2);
------------------------
@Override
public void onTaskComplete(String result, BackgroundType type) {
switch(type){
case GET:
break;
case POST:
break;
}
}

Update android UI from do in background task

If you want to use the UI from background thread then use runOnUiThread as below in doInBackground

runOnUiThread(new Runnable(){
public void run() {
// update UI
}

right way to write code for UI and background tasks

There are many ways, to design the structure of an Android app. Your question is very general, so my answer is , too.

To structure your project, you can use the MVC pattern, that can easily used with Android:

  • Model: mostly keeps data, like in lists, arrays, strings etc
  • Controller: works with data of model, runs the logic
  • View: userinterface, that can display data from model and/or run logic from controller

The question, wether to separate with packages or classes can't be answered in general. Both are useful for many cases. In my point of view the following structure for an easy example would be useful:

  • [Package] view:

    • Activty1.java
    • Activty2.java
  • [Package] model:

    • Activty1DataModel.java
    • Activty2DataModel.java
  • [Package] controller:

    • Activty1Logic.java
    • Activty2Logic.java

Heavier tasks should be run on an AsyncTaks on Android and not on UIThread (e.g. because of GUI freezes). The AsyncTask runs operations in a new seperate thread. The onPostExecute method is executed after finishing the task and runs on the UI thread, so you can interact with the view from here directly.

For real long running tasks, you should use background services.

When you want to interact with an UI from another thread, you have to run the operations explicit on the UI thread e.g. like this:

MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});

Another way to interact with the UI is to use Interfaces / Listeners.

To gather data from a web service, you can use an http client with an AsyncTask, but you must not run network operations from the UI thread (would result in an exception). Here is an example.

Next time please ask several questions in different posts, not all in one.

How to create a task that runs in the background in Android

For this you can use application component that can perform long-running operations in the background and does not provide a user interface.

For this i will suggest you links:

http://developer.android.com/guide/components/services.html

http://www.javacodegeeks.com/2014/01/android-service-tutorial.html

How to accomplish task of playing recording in background and work on different activities?

I have created a working sample for you to understand the concept fully.
I created a service as you wanted to play the media inside service.

Otherwise, service is not needed in this case, rather we can directly use the MediaPlayer api to play/pause and stop songs, by keeping a singleton object.

Also, the player controls need not to be on each activity screen, rather they can be part of your action bar.

Let me know if you are interested in seeing an example where player controls are in action bar and singleton used for media play instead of having seperate service as in my example, I will create a project and post the same.

( Tested in Note2 and Nexus emulator )

URL of the project : Posted in Git Hub.

https://github.com/gansBhat/AndroidProjects/tree/master

Also posted in Google drive

https://drive.google.com/folderview?id=0BxHClVwHSqq5dVRvT1Qyd0hYN0k&usp=sharing

Android: Communication and coordination between UI-thread and other thread

It is dengerious to use get() method to get the result from async task because It blocks the UI Thread.
use This Thread where I provided a reusable solutionCallback mechanism to get result from async thread without blocking UI Thread

I have implemented that with the help of lapslaz

public JsonData(YourActivityClass activity) 
{
this.activity=activity;
mProgressDialog = new ProgressDialog(activity);

}
protected void onPostExecute(String jsondata) {
if (mProgressDialog != null || mProgressDialog.isShowing()){
mProgressDialog.dismiss();
}
if(jsondata!=null) {
activity.yourcallback(jsondata)
}

}

And define the yourcallback() in YourActivityClass

private void yourcallback(String data) {
jsonRecordsData=data;
showRecordsFromJson();

}

Correct way to communicate the result of a background thread to the Ui Thread in Android

Background

In Android, when an application is launched, the system creates a thread of execution for the application, called main thread (also known as the UI thread). Google introduces the main thread and its responsible as below.

The main thread has a very simple design: Its only job is to take and
execute blocks of work from a thread-safe work queue until its app is
terminated. The framework generates some of these blocks of work from
a variety of places. These places include callbacks associated with
lifecycle information, user events such as input, or events coming
from other apps and processes. In addition, app can explicitly enqueue
blocks on their own, without using the framework.

Nearly any block of code your app executes is tied to an event
callback, such as input, layout inflation, or draw. When something
triggers an event, the thread where the event happened pushes the
event out of itself, and into the main thread’s message queue. The
main thread can then service the event.

While an animation or screen update is occurring, the system tries to
execute a block of work (which is responsible for drawing the screen)
every 16ms or so, in order to render smoothly at 60 frames per second.
For the system to reach this goal, the UI/View hierarchy must update
on the main thread. However, when the main thread’s messaging queue
contains tasks that are either too numerous or too long for the main
thread to complete the update fast enough, the app should move this
work to a worker thread. If the main thread cannot finish executing
blocks of work within 16ms, the user may observe hitching, lagging, or
a lack of UI responsiveness to input. If the main thread blocks for
approximately five seconds, the system displays the Application Not
Responding (ANR) dialog, allowing the user to close the app directly.

To update a View, you must do it on the main thread, if you try to update in a background thread, the system will throw CalledFromWrongThreadException.

How to update a View on the main thread from a background thread?

The main thread has a Looper and a MessageQueue assigned with it. To update a View, we need to create a task then put it to the MessageQueue. To do that Android provides
Handler API which allows us to send a task to the main thread's MessageQueue for executing later.

// Create a handler that associated with Looper of the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());

// Send a task to the MessageQueue of the main thread
mainHandler.post(new Runnable() {
@Override
public void run() {
// Code will be executed on the main thread
}
});

To help developers easy to communicate with the main thread from a background thread, Android offers several methods:

  • Activity.runOnUiThread(Runnable)

  • View.post(Runnable)

  • View.postDelayed(Runnable, long)

Under the hood, they use Handler API to do their jobs.

Back to your question

AsyncTask

This is a class that is designed to be a helper class around Thread and Handler. It's responsible for:

  • Create a thread or pool of thread to do a task in the background

  • Create a Handler that associated with the main thread to send a task to the main thread's MessageQueue.

  • It is deprecated from API level 30

ThreadPoolExecutor

Create and handle a thread in Java is sometimes hard and might lead to a lot of bugs if developers do not handle it correctly. Java offers the ThreadPoolExecutor to create and manage threads more efficiently.

This API does not provide any method to update the UI.

Kotlin Coroutines

Coroutines is a solution for asynchronous programming on Android to simplify code that executes asynchronously. But it only available for Kotlin.

So my question is, what is the correct way of communicate the result
of background thread when this finish?.

1. Using Handler or mechanism built on Handler

1.1. If a thread is bounded with Activity/Fragment:

  • Activity.runOnUiThread(Runnable)

1.2. If a thread has a reference to a view, such as Adapter class.

  • View.post(Runnable)

  • View.postDelayed(Runnable, long)

1.3. If a thread does not bound to any UI element, then create a Handler on your own.

Handler mainHandler = new Handler(Looper.getMainLooper);

Note: A benefit of using Handler is you can use it to do 2 ways communication between threads. It means from a background thread you can send a task to the main thread's MessageQueue and from the main thread, you can send a task to the background's MessageQueue.

2. Using BroadcastReceiver

This API is designed to allow Android apps can send and receive broadcast messages from the Android system, other apps or components (Activity, Service, etc) inside the app, similar to publish-subscribe design partern.

Because of the BroadcastReceiver.onReceive(Context, Intent) method is called within the main thread by default. So you can use it to update the UI on the main thread. For example.

Send data from a background thread.

// Send result from a background thread to the main thread
Intent intent = new Intent("ACTION_UPDATE_TEXT_VIEW");
intent.putExtra("text", "This is a test from a background thread");
getApplicationContext().sendBroadcast(intent);

Receive data from activity/fragment

// Create a broadcast to receive message from the background thread
private BroadcastReceiver updateTextViewReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String text = intent.getStringExtra("text");
myTextView.setText(text);
}
};

@Override
protected void onStart() {
super.onStart();
// Start receiving the message
registerReceiver(updateTextViewReceiver, new IntentFilter("ACTION_UPDATE_TEXT_VIEW"));
}

@Override
protected void onStop() {
// Stop receving the message
unregisterReceiver(updateTextViewReceiver);
super.onStop();
}

This method is usually used to communicate between Android apps or Android apps with the system. Actually, you can use it to communicate between components in Android app, such as (Activity, Fragment, Service, Thread, etc.), but it requires a lot of code.

If you want a similar solution but less code, easy to use, then you can use the following method.

3. Using EventBus

EventBus is a publish/subscribe event bus for Android and Java. If you want to execute a method that runs on the main thread, just mark it with @Subscribe(threadMode = ThreadMode.MAIN) annotation.

// Step 1. Define events
public class UpdateViewEvent {
private String text;

public UpdateViewEvent(String text) {
this.text = text;
}

public String getText() {
return text;
}
}

// Step 2. Prepare subscriber, usually inside activity/fragment
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
myTextView.setText = event.getText();
};

// Step 3. Register subscriber
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

// Step 4. Unregister subscriber
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}

// Step 5. Post events from a background thread
UpdateViewEvent event = new UpdateViewEvent("new name");
EventBus.getDefault().post(event);

This is useful when you want to update a View when the activity/fragment is visible to users (they are interacting with your app).



Related Topics



Leave a reply



Submit