I have that AsyncTask code
public class DiceTask extends AsyncTask<Socket, Void, int[]> {
private int[] arrayFromServer = new int[8];
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected int[] doInBackground(Socket...params) {
Socket soc = params[0];
try {
ObjectInputStream ois = new ObjectInputStream(soc.getInputStream());
int[] tempArray = (int[]) (ois.readObject());
return tempArray;
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
#Override
protected void onProgressUpdate(Void...arg1) {
}
#Override
protected void onPostExecute(int[] result) {
arrayFromServer = result;
}
public int[] getTempDice() {
return arrayFromServer;
}
}
where is called this way into my main thread.
rollDiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rollDiceButton.setEnabled(false);
rollDice();
task.execute(socket);
tempArray = task.getTempDice();
printDice(tempArray,pDice);
clickableDice(pDice);
}
});
where I am getting a null tempArray. If I change my onPreExecute to this
#Override
protected void onPreExecute() {
super.onPreExecute();
for(int i = 0; i < arrayFromServer.length; i++) {
arrayFromServer[i] = 1;
}
}
I am getting my dice as it should, all are one. The code I am running into the rollDice() is this
public void rollDice() {
try {
DataOutputStream sout = new DataOutputStream(socket.getOutputStream());
String line = "dice";
PrintStream out = new PrintStream(sout);
out.println(line);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
and I can see the results in the server.
You don't need to implement onPostExecute in your AsyncTask class definition. You also don't need the getTempDice function. You just need to override onPostExecute in an anonymous class and run your UI code in it.
rollDiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rollDiceButton.setEnabled(false);
rollDice();
task = new DiceTask() {
#Override
public void onPostExecute(int[] result) {
tempArray = result;
printDice(tempArray,pDice);
clickableDice(pDice);
}
}.execute(socket);
}
});
Children of AsyncTask run in parallel with main Thread, you are trying access the attribute arrayFromServer right after to start the Thread. It's recommended you use a callback to retried the value wanted, making sure you get the value after Thread is done.
Making the follow changes can solve your problem. Let me know if you understand.
public class DiceTask extends AsyncTask<Socket, Void, int[]> {
public interface Callback {
void onDone(int[] arrayFromServer);
}
private Callback mCallback;
public DiceTask(Callback c) {
mCallback = c;
}
#Override
protected int[] doInBackground(Socket...params) {
Socket soc = params[0];
try {
ObjectInputStream ois = new ObjectInputStream(soc.getInputStream());
int[] tempArray = (int[]) (ois.readObject());
return tempArray;
} catch (IOException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(int[] result) {
mCallback.onDone(result);
}
}
rollDiceButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rollDiceButton.setEnabled(false);
rollDice();
new DiceTask(new Callback() {
public void onDone(int[] tempArray) {
printDice(tempArray,pDice);
clickableDice(pDice);
}
}).execute(socket);
}
});
Related
I'm calling async tasks in a loop on the onPostExecute() of an asyncTask. I want the control to wait until response of all the tasks is not receieved cause I'm collecting the response in a single arrayList which i have to pass a callback method after all the asyncTasks called in the loop are finished.
I'm avoiding to use the AsyncTask.get() as it blocks the main thread.
public class CallServerAsync extends AsyncTask<AsyncHttpRequestBo, Void, ArrayList<ArrayList<AsyncHttpRequestBo>>> implements PlatwareResponseListener {
PlatwareClientCommonUtils clientCommonFunctions;
Context context;
String url;
PlatwareResponseListener listener;
private ProgressDialog progressDialog;
ArrayList<AsyncHttpResponseBo> processResponseList = null;
ArrayList<AsyncHttpResponseBo> responseList = null;
public CallServerAsync(Context context, PlatwareResponseListener listener) {
this.context = context;
clientCommonFunctions = new PlatwareClientCommonUtils(context);
url = clientCommonFunctions.getServerUrlPrimary();
this.listener = listener;
responseList = new ArrayList<AsyncHttpResponseBo>();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(context, "Please wait", "Downloading...");
}
#Override
protected ArrayList<ArrayList<AsyncHttpRequestBo>> doInBackground(AsyncHttpRequestBo... params) {
ArrayList<ArrayList<AsyncHttpRequestBo>> requestLists = clientCommonFunctions.generateRequestList(params);
return requestLists;
}
#Override
protected void onPostExecute(ArrayList<ArrayList<AsyncHttpRequestBo>> result) {
for (ArrayList<AsyncHttpRequestBo> httpRequestList : result) {
CallserverSubAsync callserverSubAsync = new CallserverSubAsync(context, this);
callserverSubAsync.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, httpRequestList);
// ArrayList<AsyncHttpResponseBo> processResponseList = null;
// try {
// processResponseList = callserverSubAsync.get();
// } catch (InterruptedException e) {
// e.printStackTrace();
// } catch (ExecutionException e) {
// e.printStackTrace();
// }
}
listener.onAsyncTaskCompleted(responseList, listener);
progressDialog.dismiss();
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
progressDialog.dismiss();
super.onCancelled();
}
#Override
public void onAsyncTaskCompleted(ArrayList<AsyncHttpResponseBo> responseList, PlatwareResponseListener listener) {
if (listener instanceof CallServerAsync) {
processResponseList = responseList;
for (AsyncHttpResponseBo responseBo : processResponseList) {
this.responseList.add(responseBo);
}
}
}
I would like to use the information of 'result' in the XMLRPCMethod. When the thread is finished the correct data is in the result object.
This is a code snipped from my OpenerpRPC.java class.
class XMLRPCMethod extends Thread {
private String method;
private Object[] params;
private Handler handler;
public Object result;
private OpenerpRpc callBack;
public XMLRPCMethod(String method, OpenerpRpc callBack) {
this.method = method;
this.callBack = callBack;
handler = new Handler();
}
public void call() {
call(null);
}
public void call(Object[] params) {;
this.params = params;
start();
}
#Override
public void run() {
try {
result = client.callEx(method, params);
handler.post(new Runnable() {
public void run() {
try {
callBack.resultcall(result);
} catch (XMLRPCException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (final XMLRPCFault e) {
handler.post(new Runnable() {
public void run() {
Log.d("Test", "error", e);
}
});
} catch (final XMLRPCException e) {
handler.post(new Runnable() {
public void run() {
Throwable couse = e.getCause();
if (couse instanceof HttpHostConnectException) {
Log.d(TAG, "error"+uri.getHost());
} else {
Log.d("Test", "error", e);
}
Log.d("Test", "error", e);
}
});
}
}
}
My result call in the OpenerpRpc class looks like:
public void resultcall(Object result) throws XMLRPCException{
allres=result;
if (rtype.equals("login")){
//Isn't impossible cast the result var with (String) because cause crash..why?
userid=""+result;
}
if (rtype.equals("read")){
//Isn't impossible cast the result var with (String) because cause crash..why?
// userid=""+result;
}
// name of callback function to use in parent class (MainActivity) for receive data
this.parent.oerpcRec(rtype,allres);
}
This is how i can receive the data in mainactivity
#SuppressWarnings("unchecked")
public void oerpcRec(String rtype,Object res) throws XMLRPCException{
if (rtype=="login"){
connector.setModel("res.users");
Object[] Ids = {Integer.parseInt(connector.userid)};
// set here the fields you wont loads
Object[] values={"name"};
connector.Read(Ids,values);
}
if(rtype=="read"){
Object[] ret=(Object[])res;
Map<String, Object> map1 = (Map<String, Object>) ret[0];
if(ret.length > 1){
}
}
}
But how can i get this information in my mainactivity? I only get the information of the login id value. When I put a breakpoint in the thread it only goes to the function resultcall when I try to login.
...
public void onClick(View v) {
try {
//here set user and pass for login
connector.Login(USER,PASS);
Object[] ids = {31,30,28,26};
Object[] params ={"partner_id","tax_line","section_id","invoice_line"};
connector.Read(ids,params);
//get information of openERP for specific id's
} catch (XMLRPCException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Use an interface
public interface MyListener {
public void callback(Object result);
}
Your MainActivity must implement the interface
public class MyActivity extends Activity implements MyListener {
...
...
...
#override
public void callback(Object result) {
// getting the result value.
}
}
So when your thread finish, execute the callback() method:
MyListener ml;
ml.callback(result);
and the callback() method of you MainActivity will receive the object.
When I retrieve the value in results activity. I get nothing, I guess the the value is not being passed from doInBackground to onPostExecute. Any idea what's wrong? or am I passing it the wrong way
class calculateTask extends AsyncTask<String, String, String>
{
#Override
protected String doInBackground(String... params) {
Thread t= new Thread();
try {
t.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int pix=0;
int circ=0;
int width1=mBitmap.getWidth();
int height1=mBitmap.getHeight();
for(int i=0;i<width1;i++)
{
for(int j=0;j<height1;j++)
{
if(mBitmap.getPixel(i, j)==Color.WHITE)
{
pix++;
}
if(mBitmap.getPixel(i, j)==Color.LTGRAY)
{
circ++;
}
}
}
int percentage=100-((pix-circ))*100 ;
String p=intToChar(array,percentage);
return p;
}
#Override
protected void onPostExecute(String p) {
Intent i= new Intent(circle1.this,results.class);
i.putExtra("perc", p);
startActivity(i);
//super.onPostExecute(result);
}
}
public String intToChar(char[] array, int pix) {
// TODO Auto-generated method stub
String b="";
int i = array.length - 1;
while (pix > 0 && i >= 0) {
array[i--] = (char) (48 + pix % 10);
pix /= 10;
} b = new String(array);
return b;
}
I would use a global variable. Then assign value to the global variable in doInBackground, and then retrieve it in onPostExecute.
EDIT:
Many things are wrong.
Here is one of my examples from code
private class Load extends AsyncTask<Void, Void, Void>
{
private ProgressDialog progressDialog;
private Context context;
private boolean internet, refresh;
public Load(Context context, boolean internet, boolean refresh)
{
this.internet = internet;
this.refresh = refresh;
this.context = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
progressDialog = ProgressDialog.show(context, null, "Loading data ...");
}
#Override
protected Void doInBackground(Void... voids)
{
taskComplete = false;
while (!taskComplete)
{
getData(this.internet);
try
{
Thread.sleep( 1000 );
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
populateData();
progressDialog.dismiss();
}
}
Try imitating this. getData sets taskComplete to true once it is done.
I want to show a progress dialog while loading some data from remote server :
I'm using the following thread in order to get the data and it's working, but i'm not able to show the progress bar on the activity:
public class Request {
public String text ;
public boolean downloadText(String urlStr) {
final String url = urlStr;
new Thread () {
public void run() {
int BUFFER_SIZE = 2000;
InputStream in = null;
Message msg = Message.obtain();
msg.what=2;
try {
in = openHttpConnection(url);
InputStreamReader isr = new InputStreamReader(in);
int charRead;
text = "";
char[] inputBuffer = new char[BUFFER_SIZE];
while ((charRead = isr.read(inputBuffer))>0)
{
//---convert the chars to a String---
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
text += readString;
inputBuffer = new char[BUFFER_SIZE];
}
Bundle b = new Bundle();
b.putString("text", text);
msg.setData(b);
in.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
would you please tell me how can i do it !!
create the class as below and just call the object of this class.
class MyTask extends AsyncTask<Void, Void, Void> {
ProgressDialog Asycdialog = new ProgressDialog(ActivityName.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
Asycdialog.setMessage("Loading...");
Asycdialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
// do the task you want to do. This will be executed in background.
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Asycdialog.dismiss();
}
}
Use progressDialog
final ProgressDialog progress=ProgressDialog.show(youractivity.this,"","message");
new Thread()
{
public void run()
{
try{
youractivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
// your code
}
});
}
catch(Exception e)
{
}
progress.dismiss();
}
}.start()
Also, note that if you want to use Toast, you should use runOnUiThread
If you do not want to change the structure of your code, you can use runOnUiThread or an Handler to show and dissmiss the progress dialog. Show it when the firs line of the run method is excuted and dismiss it in the finally block.
public void run() {
runOnUiThread(new Runnable() {
public void run(){
// show progress dialog
}
});
/// your code here
try {
} catch (IOException e) {
} finally {
runOnUiThread(new Runnable() {
public void run(){
// dismiss progress dialog
}
});
}
}
Create Progress Dialog in AsyncTask
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... args) {
// do background work here
return null;
}
protected void onPostExecute(Void result) {
// do UI work here
}
}
pDialog = ProgressDialog.show(context, null, "Loading...", true);
pDialog.setCancelable(false);
new Thread() {
public void run() {
// handle the exception somehow, or do nothing
// run code on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
// do yor ui part here
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}.start();
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();
}
}