Is it possible to display a message or make changes on the UI thread once Task callInBackground is finished executing?
Something like following:
Task.callInBackground(new Callable<String>() {
#Override
public String call() {
for(int i=0; i<3; i++){
Log.i("I=", String.valueOf(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String obj = "";
return null;
}
}).onSuccess(new Continuation<String, Object>() {
#Override
public Object then(Task<String> task) throws Exception {
Log.i("I=", "Counter complete");
Toast.makeText(MainLoanMemberActivity.this, "Finished", Toast.LENGTH_SHORT).show();
btnAgriLoan.setText("LOL");
return null;
}
});
At the moment there is no Toast message displayed and there is no crash as well.
Looking for an equivalent of AsyncTask's onPostExecute in Bolts Framework where one can add changes to UI.
Didn't realized that there are EXECUTOR's types that you can mentioned with each helper function like so: (Task.UI_THREAD_EXECUTOR)
Task.callInBackground(new Callable<String>() {
#Override
public String call() {
for(int i=0; i<3; i++){
Log.i("I=", String.valueOf(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String obj = "";
return null;
}
}).onSuccess(new Continuation<String, Void>() {
public Void then(Task<String> object) throws Exception {
Toast.makeText(MainLoanMemberActivity.this, "Finished", Toast.LENGTH_SHORT).show();
btnAgriLoan.setText("LOL");
return null;
}
}, Task.UI_THREAD_EXECUTOR);
Docs helped!
Related
I'm using android socket.io but the problem is that emit event runs twice instead of once , i mean that i wrote just one emit code in the onCreate method , but it sends two request for the server ?
I searched alot but not found anything .
I use node js in the backend ,and my code has not any problems .
Is there a bug in socket.io for android ?
Here is my code :
SocketManager.getInstance().connect();
// Creating Bids
final Handler mHandler04 = new Handler(Looper.getMainLooper());
mHandler04.post(new Runnable() {
#Override
public void run() {
SocketManager.getInstance().getSocket().emit("allc", "some");
SocketManager.getInstance().getSocket().on("allcRes", new Emitter.Listener() {
#Override
public void call(final Object... args) {
g.context.runOnUiThread(new Runnable() {
#Override
public void run() {
JSONArray jsonArray = (JSONArray) args[0];
arrayComps.clear();
Log.d(TAG, "run: " + jsonArray);
try {
for (int i = 0; i < jsonArray.length(); i++) {
createView(jsonArray.getJSONObject(i).getString("title"), jsonArray.getJSONObject(i).getString("realprice"), jsonArray.getJSONObject(i).getString("id"), jsonArray.getJSONObject(i).getString("starttime"), jsonArray.getJSONObject(i).getString("img"));
CustomViewCompetition css = (CustomViewCompetition) LinearLayoutItemHolder.getChildAt(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
final Handler bidsupdateHandler = new Handler(Looper.getMainLooper());
bidsupdateHandler.post(new Runnable() {
#Override
public void run() {
SocketManager.getInstance().getSocket().on("bidsupdate", new Emitter.Listener() {
#Override
public void call(final Object... args) {
final JSONArray jsonArray = (JSONArray) args[0];
g.context.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "run in bidsupdate");
try {
for (int i = 0; i < jsonArray.length(); i++) {
bidsMap.put(jsonArray.getJSONObject(i).getInt("key"), jsonArray.getJSONObject(i).getInt("value"));
}
for (int i = 0; i < LinearLayoutItemHolder.getChildCount(); i++) {
CustomViewCompetition cs = (CustomViewCompetition) LinearLayoutItemHolder.getChildAt(i);
Log.d(TAG, "run in cs " + cs.txtCsRealPrice.getText());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
the Problem is when i get the cs.txtCsTitle.getText() it is just showing me one of them
Add this line:
SocketManager.getInstance().getSocket().emit("allc", "some");
just after:
SocketManager.getInstance().connect();
So your code will be like
SocketManager.getInstance().connect();
SocketManager.getInstance().getSocket().emit("allc", "some");
And remove from where you are already using in handler. Also you dont need handlers why you are using handlers? Create your listener and emit your subscription out of handlers it needs to be created or subscribed once. On creation of emitter listener pass views if you need to update any view. then update the views here you may need runnable to update UI on uiThread.
Create Class as follows:
public class YourListener implements Emitter.Listener
{
private yourView view;
public YourListener (View view)
{
this.view = view;
}
#Override
public void call(Object... args)
{
// do your work here
}
}
and replace below code :
SocketManager.getInstance().getSocket().on("allcRes", new Emitter.Listener() {
#Override
public void call(final Object... args) {
g.context.runOnUiThread(new Runnable() {
#Override
public void run() {
JSONArray jsonArray = (JSONArray) args[0];
arrayComps.clear();
Log.d(TAG, "run: " + jsonArray);
try {
for (int i = 0; i < jsonArray.length(); i++) {
createView(jsonArray.getJSONObject(i).getString("title"), jsonArray.getJSONObject(i).getString("realprice"), jsonArray.getJSONObject(i).getString("id"), jsonArray.getJSONObject(i).getString("starttime"), jsonArray.getJSONObject(i).getString("img"));
CustomViewCompetition css = (CustomViewCompetition) LinearLayoutItemHolder.getChildAt(i);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
with:
SocketManager.getInstance().getSocket().on("your_subscription", new YourListener (yourView));
new AsyncTask<Ticket, Void, List<TPVLine>>() {
#Override
protected List<TPVLine> doInBackground(Ticket... params) {
List<TPVLine> lines;
while (true){
Log.d(TAG, "Waiting for data base response");
try {
lines = params[0].getLines();
Log.d(TAG, "Data base response completed");
break;
}catch (SQLiteException | NullPointerException ex){
ActiveAndroid.clearCache();
Log.d(TAG, "Cleaning cache");
Log.wtf(TAG, ex.toString());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return lines;
}
#Override
protected void onPostExecute(List<TPVLine> aVoid) {
super.onPostExecute(aVoid);
linesTPV = new ArrayList<TPVLine>();
if (aVoid != null){
linesTPV = aVoid;
}
linesTPV.addAll(noSavedLines);
mainActivity.getTpvFragment().resetPrice();
notifyDataSetChanged();
if (linesTPV.size() == 0){
mainActivity.getTpvFragment().getListContainer().setVisibility(View.INVISIBLE);
mainActivity.getTpvFragment().getMessageContainer().setVisibility(View.VISIBLE);
}else {
mainActivity.getTpvFragment().getListContainer().setVisibility(View.VISIBLE);
mainActivity.getTpvFragment().getMessageContainer().setVisibility(View.INVISIBLE);
}
notifyDataSetChanged();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mainActivity.getCurrentTicket());
This are the calls, first in Ticket.java
public List<TPVLine> getLines() {
return new Select().from(TPVLine.class).where("Ticket = ?", this.getId()).execute();
}
The second is in TPVLine.java
public static List<TPVLine> getLines(Ticket ticket){
return new Select().from(TPVLine.class).where("Ticket = ?", ticket.getId()).orderBy("Id ASC").execute();
}
The issue is caused when i call TPVLine.class, i make sure first that Ticket != null. I'm using ActiveAndroid to manage the database
you are returning null instead of lines in your asynctask doInBackground event.
return lines;
I have a String variable in main class private String gameEnabled = "0"; , how can I update the variable immediately inside my AsyncHttpResponseHandler to avoid getting value before completion of AsyncTask?
My AsyncHttpResponseHandler:
try {
APICaller.App_Game_Enabled(getApplicationContext(), new AsyncHttpResponseHandler() {
#Override
public void onFailure(Throwable arg0, String error) {
}
#Override
public void onSuccess(String response) {
try {
JSONArray json_Response = APICaller.XMLtoJsonArray(response);
if (json_Response.length() > 0) {
JSONObject dataNode = json_Response.getJSONObject(0);
gameEnabled = dataNode.getString("result");
} else {
//showAlert(getResources().getString(R.string.ShowAlert_Alert), getResources().getString(R.string.ShowAlert_CreatorAccess));
}
// Progress_Hide();
} catch (Exception ex) {
ex.printStackTrace();
//finish();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
Expected to update gameEnabled to "1" after this code but I always get the default "0". How can I deal with this if I need to follow below conditions? Thanks in advanced.
Use AsyncHttpResponseHandler
Update gameEnabled inside the AsyncHttpResponseHandler class and use it outside the class
My MainActivity has 2 views: TextView and a Button. On button click, I am running an AsyncTask which further creates 10 new AsyncTasks for network operations. Every new task creation is delayed by 1 sec. The code is:
public class MainActivity extends ActionBarActivity
{
TextView tv;
Button t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
t = (Button) findViewById(R.id.toggleButton1);
t.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
getData();
}
});
}
void getData()
{
SuperNetworkAsyncTask s = new SuperNetworkAsyncTask();
s.execute("");
}
private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
for(int i=0;i<10;i++)
{
{
nTask = new NetworkAsyncTask();
nTask.execute("");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return "";
}
#Override
protected void onPostExecute(String result)
{
}
}
private class NetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
return String.valueOf(System.currentTimeMillis());
}
#Override
protected void onPostExecute(String result)
{
tv.setText(result);
}
}
}
I was expecting that the moment first NetworkAsyncTask execute method is called, it will start execution. But when I run it, I do not find any NetworkAsyncTask begin its execution until the control comes out of SuperNetworkAsyncTask. Is there any way to push the execution of NetworkAsyncTask thread as soon as execute method is called?
Some clarifications:
Why NetworkAsyncTask are created by SuperNetworkAsyncTask? Because If I create the NetworkAsyncTask in main thread, I get my UI freeze for some time.
Why making 10 object? The purpose of NetworkAsyncTask is to read data from a server at interval of 1 sec for n seconds, here n=10.
Part 2: Updates after doing some tests.
Observation 1:
As a fellow Brian shared a way to avoid creating AsyncTasks in nested way, I tried his code:
void getData() {
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
nTask = new NetworkAsyncTask();
nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
This freezes my UI for few seconds and then the screen is updated in a fraction of second. It is quite surprising to me too.
Observation 2:
With java.lang.Thread, I experimented to make sure that 1) The threads should be executed right away when run() called. 2) The next task will be created only after previous task is finished.
Code:
public static void main(String[] args) {
myThread m;
for (int i=0;i<10;i++)
{
m=new myThread(String.valueOf(i));
m.start();
synchronized (m)
{
try {
m.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class myThread extends Thread
{
public String name = "";
public myThread(String n)
{
name = n;
}
public void run()
{
synchronized (this)
{
System.out.println(" Thread Name = " + name);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll();
}
}
}
Output:
Thread Name = 0
Thread Name = 1
Thread Name = 2
Thread Name = 3
Thread Name = 4
Thread Name = 5
Thread Name = 6
Thread Name = 7
Thread Name = 8
Thread Name = 9
Based in this, I updated my NetworkAsyncTask & SuperNetworkAsyncTask as:
private class NetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
synchronized (this)
{
return String.valueOf(System.currentTimeMillis());
}
}
#Override
protected void onPostExecute(String result)
{
synchronized (this)
{
tv.setText(result);
notifyAll();
}
}
}
private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
for(int i=0;i<10;i++)
{
nTask = new NetworkAsyncTask();
nTask.execute(url);
synchronized (nTask)
{
try {
nTask.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return "";
}
#Override
protected void onPostExecute(String result)
{
}
}
With this code the wait() keeps on waiting indefinitely.
Finally I replaced:
nTask.execute(url);
with
nTask.executeOnExecutor(THREAD_POOL_EXECUTOR, "");
This worked well as expected.
The UI will be updated only at onPostExecute(). See notes on AsyncTask
Click here! And Try to avoid 10 AysncTasks, it does not make any sense.
You don't need to use a "super async task" use a runnable and then create new async tasks in parallel
void getData() {
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
nTask = new NetworkAsyncTask();
nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(runnable).start();
}
Post honeycomb you can specify to run async tasks in parallel
An AsyncTask should be started in the UI thread, not on the one doInBackground runs on. You could call publishProgress after every sleep, and spawn each AsyncTask in the resulting calls to onProgressUpdate, which run on the UI thread.
I've seen a bunch of posts related to this, but none seem to have the same issue I'm getting. GetBusinessRulesTask extends AsyncTask. When I execute this in a unit test case the onPostExecute() never gets called. However, if I use the real client code then onPostExecute() is called everytime. Not sure what I'm doing wrong here.
Test Case:
package com.x.android.test.api;
import java.util.concurrent.CountDownLatch;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.widget.Button;
import com.x.android.api.domain.businessrule.BusinessRules;
import com.x.android.api.exception.NetworkConnectionException;
import com.x.android.api.tasks.GetBusinessRulesTask;
import com.x.android.test.activity.SimpleActivity;
public class GetBusinessRulesTaskTest
extends
ActivityInstrumentationTestCase2<SimpleActivity> {
SimpleActivity mActivity;
Button mButton;
public GetBusinessRulesTaskTest() {
super("com.x.android.test.activity", SimpleActivity.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
mActivity = this.getActivity();
mButton = (Button) mActivity
.findViewById(com.x.android.test.activity.R.id.b1);
}
public void testPreconditions() {
assertNotNull(mButton);
}
#UiThreadTest
public void testCallBack() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
final GetBusinessRulesTask task = (GetBusinessRulesTask) new GetBusinessRulesTask(
new GetBusinessRulesTask.Receiver<BusinessRules>() {
#Override
public void onReceiveResult(BusinessRules rules, Exception e) {
assertNotNull(rules);
assertNull(e);
signal.countDown();// notify the count down latch
}
});
task.start(mActivity.getApplicationContext());
try {
signal.await();// wait for callback
} catch (InterruptedException e1) {
fail();
e1.printStackTrace();
}
}
}
OnPostExecute:
#Override
protected void onPostExecute(AsyncTaskResponse<O> response) {
Log.d(TAG, "onPostExecuted");
if (mReceiver != null) {
mReceiver.onReceiveResult(response.getResponse(), response.getException());
}
}
DoInBackground:
#Override
protected AsyncTaskResponse<O> doInBackground(I... params) {
Log.d(TAG, "doInBackgroundr");
try {
Uri uri = createUri(params);
mBaseRequest = new GetLegacyRequest(uri);
String json = mBaseRequest.executeRequest();
O response = deserializeJson(json);
Log.d(TAG, "Returning AsyncTaskResponse");
return new AsyncTaskResponse<O>(response, null);
} catch (Exception e) {
Log.e(TAG, "Error", e);
/*
AsyncTaskResponse<O> maintenance = ReadBusinessControlledPropertiesTask.blockingCall(mServiceLocatorUrl);
if(maintenance.getException() == null) {
MaintenanceException mExcep = new MaintenanceException( maintenance.getResponse());
if (mExcep.isUnderMaintenance())
return new AsyncTaskResponse(null,mExcep);
}*/
return new AsyncTaskResponse<O>(null, e);
}
}
Start method()
public AsyncTask<Void, Void, AsyncTaskResponse<BusinessRules>> start(
Context context) throws NetworkConnectionException {
super.start(context);
Log.d(TAG, "start");
return execute();
}
FOUND THE ISSUE. Don't make your AsyncTask final and put it inside the runnable.
The fix:
public void testCallBack() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
// Execute the async task on the UI thread! THIS IS KEY!
runTestOnUiThread(new Runnable() {
#Override
public void run() {
try {
GetBusinessRulesTask task = (GetBusinessRulesTask)new GetBusinessRulesTask(new GetBusinessRulesTask.Receiver<BusinessRules>() {
#Override
public void onReceiveResult(
BusinessRules rules, Exception e) {
assertNotNull(rules);
assertNull(e);
signal.countDown();// notify the count downlatch
}
});
task.start(mActivity.getApplicationContext());
} catch (Exception e) {
Log.e(TAG, "ERROR", e);
fail();
}
}
});
try {
signal.await();// wait for callback
} catch (InterruptedException e1) {
fail();
e1.printStackTrace();
}
}
FOUND THE ISSUE. Don't make your AsyncTask final and put it inside the runnable.
The fix:
public void testCallBack() throws Throwable {
final CountDownLatch signal = new CountDownLatch(1);
// Execute the async task on the UI thread! THIS IS KEY!
runTestOnUiThread(new Runnable() {
#Override
public void run() {
try {
GetBusinessRulesTask task = (GetBusinessRulesTask)new GetBusinessRulesTask(new GetBusinessRulesTask.Receiver<BusinessRules>() {
#Override
public void onReceiveResult(
BusinessRules rules, Exception e) {
assertNotNull(rules);
assertNull(e);
signal.countDown();// notify the count downlatch
}
});
task.start(mActivity.getApplicationContext());
} catch (Exception e) {
Log.e(TAG, "ERROR", e);
fail();
}
}
});
try {
signal.await();// wait for callback
} catch (InterruptedException e1) {
fail();
e1.printStackTrace();
}
}