AsyncTask ProgressBar 更新中的多线程概念wait() 和notify()

问题描述

这里的后台方法需要根据列表的大小调用多个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:”。