问题描述
这里的后台方法需要根据列表的大小调用多个API请求。但我正在使用 while()。它不会等到请求 API 并得到响应。所以我在里面使用线程。如何同步。 API调用成功后,只需要调用下一个请求即可。
private class AsyncPost extends AsyncTask<String,Void,Void> {
String strResult = "";
@Override
protected Void doInBackground(String... params) {
try {
GlobalVariables.rqCount=0;
mHandler=null;
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(android.os.Message message) {
onProgressUpdate(message.getData().getString("MessageString"));
}
};
strResult = "ENSURE NOT EMPTY";
strResult=getRequestResult(Listactivity.this,50,mHandler);
}
catch (Exception e)
{
dialog.dismiss();
}
return null;
}
@Override
protected void onPostExecute(Void resultGetlogin) {
try {
dialog.dismiss();
if(strResult.equals("Success")){
CustomDiallog.showAlertDialog(Listactivity.this,"Successfully!!");
}else{
CustomDiallog.showAlertDialog(Listactivity.this,"FAIL!!");
}
} catch (Exception e) {
dialog.dismiss();
}
}
protected void onProgressUpdate(String... values) {
dialog.setMessage(""+values[0]);
}
protected void onPreExecute() {
dialog = ProgressDialog.show(Sync_Bulk.this,"","");
}
}
这个线程正在使用但崩溃帮助我
private class getRequestResult(Context context,int allSynclimit,Handler handler2){
new Thread(new Runnable() {
@Override
public void run() {
try {
inalContext.wait();
if (res_result.equals("Success")) {
result[0] = "Success";
} else {
result[0] = "fail";
}
}catch (Exception e){
e.printstacktrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (finalContext) {
postRequest((Activity) finalContext,list); // This is Api method and notify() is called
}
}
}).start();
}
}
解决方法
你需要类似的东西:
/** Class for Synchronize two Threads */
private static class SyncObj<T> {
@Nullable
private T mValue = null;
public SyncObj(@Nullable final T initValue) { this.mValue = initValue; }
public void set(@Nullable final T value) { this.mValue = value; }
@Nullable
public T get() { return this.mValue; }
}
/** A Thread is used instead of {@link AsyncPost} */
private class AsyncPost extends Thread {
private Handler mAsyncPostHandler;
private final Handler mMainThreadHandler;
private boolean mOnPreExecuted = false;
public AsyncPost() {
mMainThreadHandler = new Handler(Looper.getMainLooper()) {
@UiThread @MainThread
@Override
public void handleMessage(@NonNull final Message message) {
switch (message.what) {
case 111: {
@Nullable
final String cRequestText = (String)message.obj;
if (cRequestText == null) break;
dialog.setMessage(cRequestText);
break;
}
default: { } //all Runnables sent to "mMainThreadHandler" are executed "here"
}
}
};
}
@WorkerThread
@Override
public void run() {
Looper.prepare();
mAsyncPostHandler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(@NonNull final Message message) {
switch (message.what) {
case -1: {
final Looper cMyLooper = Looper.myLooper();
if (cMyLooper != null) cMyLooper.quit();
break;
}
case 555: {
if (!mOnPreExecuted) {
//esecuted on Main/UIThread at first API Request...
OnMainThreadRun(new Runnable() { //SAME AS "onPreExecute()"
@Override
public void run() { dialog = ProgressDialog.show(Sync_Bulk.this,"",""); }
});
mOnPreExecuted = true;
}
final List<?> cList = (List<?>)message.obj;
if (cList == null) break;
final SyncObj<String> cSyncObj = new SyncObj<>(null);
//loop through the List
@Nullable
String cRequesteResult;
for (final Object cItem : cList) {
//call API Request for each item in the List...
postRequest(cSyncObj,cItem);
try {
//...wait until "notify()" is called
synchronized (cSyncObj) {
//loop until "SyncObj.set()" was called with a valid Value
while ((cRequesteResult = cSyncObj.get()) == null) cSyncObj.wait();
//check SyncObj result
if (cRequesteResult.equals("OK")) {
Log.i("MainActivity","Request successfully");
} else {
Log.w("MainActivity","Request failed: " + cRequesteResult);
}
//update the Dialog on Main/UIThread
OnProgressUpdate(cRequesteResult);
}
} catch (Exception e) {
Log.e("MainActivity","Stopping all Request due to Exception: " + e.getMessage());
}
}
//terminate this Thread
postToAsyncThread_Quit();
break;
}
}
}
};
Looper.loop();
this.OnMainThreadRun(new Runnable() { //SAME AS "OnPostExecute()"
@Override
public void run() {
..executed on Main/UIThread at the end of all..
}
});
}
/** Execute a {@link Runnable} on MainThread/UiThread */
@WorkerThread
private void OnMainThreadRun(@Nullable final Runnable runnable) {
if (runnable == null) return;
mMainThreadHandler.post(runnable);
}
@AnyThread
private void OnProgressUpdate(@Nullable final String text) { mMainThreadHandler.sendMessage(Message.obtain(mMainThreadHandler,111,text)); }
/** Execute a {@link Runnable} on {@link AsyncPost} Thread */
@AnyThread
private void postToAsyncThread_DoRequests(@Nullable final List<?> list) { mAsyncPostHandler.sendMessage(Message.obtain(mAsyncPostHandler,555,list)); }
/** Terminate {@link AsyncPost} Thread */
@AnyThread
private void postToAsyncThread_Quit() { mAsyncPostHandler.sendEmptyMessage(-1); }
}
private void postRequest(final SyncObj<String> syncObj,@NonNull final Object listItem) {
//execute API Request which will trigger one of Listener methods
doAsyncRequest(listItem,new ResponseListener() {
@Override
void onSuccess() {
synchronized (syncObj) {
syncObj.set("OK");
syncObj.notify();
}
}
@Override
void onFailed() {
synchronized (syncObj) {
syncObj.set("ERROR");
syncObj.notify();
}
}
});
}
private void doAllRequests(@Nullable final List<?> list) {
final AsyncPost cAsyncPost = new AsyncPost();
cAsyncPost.start();
cAsyncPost.postToAsyncThread_DoRequests(list);
}
只需调用“doAllRequests(...)”即可提供适当的列表。 一个“OnPreExecute()”类将在第一次 API 调用时执行,一个“OnPostExecute()”类将在最后一次 API 调用结束时执行。 在每次 API 调用(成功或失败)时,将从 Main/UIThread 调用“case 111:”。