AsyncTask ProgressBar 更新中的多线程概念 wait() 和 notify()
Posted
技术标签:
【中文标题】AsyncTask ProgressBar 更新中的多线程概念 wait() 和 notify()【英文标题】:Multi threading concept wait() and notify() inside AsyncTask ProgressBar update 【发布时间】:2021-03-31 06:49:34 【问题描述】:这里的后台方法需要根据列表的大小调用多个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();
【问题讨论】:
您没有发布“postRequest()”代码,所以运行“notify()”时不容易理解。也没有任何“WHILE”,那么你在哪里进行迭代?但是,您的解决方案似乎是错误的,因为“对话框”似乎是一个 UI 元素,不得直接从“doInBackground()”访问。请添加“postRequest()”代码 【参考方案1】:你需要类似的东西:
/** 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()”-like 将在第一次 API 调用时执行,单个“OnPostExecute()”-like 将在最后一次 APi 调用结束时执行。 在每次 API 调用(成功或失败)时,都会从 Main/UIThread 调用“case 111:”。
【讨论】:
感谢@emandt 的回复。我使用递归概念进行 API 请求调用。以上是关于AsyncTask ProgressBar 更新中的多线程概念 wait() 和 notify()的主要内容,如果未能解决你的问题,请参考以下文章
AsyncTask ProgressBar 更新中的多线程概念 wait() 和 notify()
使用 CountDownTimer 更新 ProgressBar
第一次进入片段ListView时AsyncTask更新progressBar的进度失败,滚动ListView后就ok了