簡體   English   中英

帶有子類AsyncTask的Android類在返回值之前等待postExecute

[英]Android Class with sub-class AsyncTask wait for the postExecute before returning the value

目前,我正在為我的項目做某事,其中我創建了一個單獨的類,該類僅處理Asynctask並獲取我傳遞的Web服務的值,並且該類應以字符串形式返回JSON響應。 現在我已經使用taskName.execute().get(); 其中它會等待任務完成,但是問題在於它還在顯示屏幕布局之前正在等待任務完成。 使我的progressDialog無用,並導致切換屏幕的延遲。 現在是我的代碼:

對於帶有AsyncTask的類:

public class UtilGetResponse {

    Context context;
    Map hash_values = new HashMap();
    int DialogType;
    String response;
    /*  
        PLAN FOR DialogTypes:
    * 0 - Standard Please wait dialog
    * 1 - Progress dialog
    * 2 - Camera upload dialog
    * */


    InputStream is = null;
    StringBuilder string_builder = null;


    public UtilGetResponse(Map values, Context baseContext, int type){
        /*initialize class and pass the hash values for parameters*/
        context = baseContext;
        hash_values.putAll(values);
        DialogType = type;
    }

    public String startTask(){
        //TODO CASE WHEN BASED ON THE DIALOG TYPE SPECIFIED
        Utilities util = new Utilities();

        if(util.isOnline(context)){
            try {
                new UploaderTaskStandard().execute().get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        return response; //THE RESPONSE ONLY SHOW ONCE THE WHOLE TASK IS COMPLETED
    }


    public class UploaderTaskStandard extends AsyncTask<Map, Void, Void> {
        ProgressDialog simpleDialog;

        @Override
        protected void onPreExecute() {
            /*Do something before the async task starts*/
            simpleDialog = new ProgressDialog(context);
            simpleDialog.setMessage("Please wait");
            simpleDialog.show();
        }

        @Override
        protected Void doInBackground(Map... maps) {
            uploadData();
            return null;
        }

        protected void onPostExecute(Void v) {
            /*Do something after the task is complete*/
            simpleDialog.dismiss();
        }
    }

    private void uploadData() {
        response = "null";
        String url = hash_values.get("url").toString().replace(" ", "%20"); //get the URL replacing the space with %20

        //If the user is trying to upload a file use this part
        try {
            HttpClient client = new DefaultHttpClient();
            HttpPost post = new HttpPost(url);
            MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

                /*This will convert the hashMap sent into individual part per key per value*/
            Set set = hash_values.entrySet();
            Iterator iterator = set.iterator();

                /*do a loop passing all the data on a string*/
            while(iterator.hasNext()) {
                Map.Entry mapEntry = (Map.Entry)iterator.next();
                String keyword = String.valueOf(mapEntry.getKey());
                String value = String.valueOf(mapEntry.getValue());

                    /*this will check if the passed data is a URL, file or a simple value*/
                if(!keyword.equals("url")){
                    if(value.matches("(.*)/(.*)")){
                        File file = new File(value);
                        Log.v("Does this exists?",String.valueOf(file.exists()));
                        if(file.exists()){
                            FileBody upload_file;
                            upload_file = new FileBody(file);
                                /*not url but file*/
                            mpEntity.addPart(keyword, upload_file);
                        }else{
                                /*not url and not file*/
                            mpEntity.addPart(keyword, new StringBody(value));
                        }
                    }else{
                            /*not URL and not file*/
                        mpEntity.addPart(keyword, new StringBody(value));
                    }
                }
            }

            post.setEntity(mpEntity);
            HttpResponse response = client.execute(post);
            HttpEntity resEntity = response.getEntity();

            is = resEntity.getContent();
        } catch (Exception e) {
            e.printStackTrace();
            response = "null";
        }

        /*convert JSON to string*/
        try{
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            string_builder = new StringBuilder();
            String line = "0";

            while ((line = reader.readLine()) != null) {
                string_builder.append(line + "\n");
            }
            is.close();
            response = string_builder.toString();
        }catch(Exception e){
            e.printStackTrace();
        }

    }

}

並稱之為:

Map hash_values = new HashMap();

        try{
            HashMap params = new HashMap<String,String>();
            params.put("param1", "YOUR_PARAM");
            params.put("url", "YOUR_WEBSERVICE_URL");

            //pass parameters
            hash_values.putAll(params);
            //start async task

            UtilGetResponse util = new UtilGetResponse(hash_values, getActivity(), 0);
            String result = util.startTask();

            Log.v("The result string",result);

        }catch (Exception e){
            e.printStackTrace();
            e.getCause();
            Toast.makeText(getActivity(), "Oops problem", Toast.LENGTH_SHORT).show();
        }

有沒有辦法讓我正確地執行此操作,而無需真正等待整個任務完成才移到下一個屏幕? 我正在考慮使用處理程序,但是無論如何我都不是很熟悉。

您的問題在於此用法

new UploaderTaskStandard().execute().get();

盡管您使用的是AsynTask,但仍使系統等到結果超出您的要求時,您需要的是一種傳遞機制,一旦結果准備好,它將通知您。 您可以采用兩種方法之一。

change to this, and implement one of below mechanism.
new UploaderTaskStandard().execute();
  1. 實施處理程序,並將結果發布回去。
  2. 實現觀察者設計模式,在其中創建帶有onResultReady之類的方法的startTask ,並將實現上述接口的類的對象傳遞給方法startTask ,並將結果通過接口機制從AsyncTask onPostExecuteonPostExecute

通過接口進行操作非常容易,這樣您的代碼將獨立於您的網絡邏輯,下面的示例代碼

// Observer listener interface design
interface ResultListener{
    // You can overload this method with data type you want to return
    public void onResultReceived();

    // Use them in a proper way for sending error message back to your program
    public void onTaskCancelled();
    public void onError();

}
 // This will be your new method signature
 public String startTask(ResultListener listener){
     // Call it liske this, passing listener reference
     new UploaderTaskStandard().execute(listener);
 }

 // This is your AsyncTask model
 public class UploaderTaskStandard extends AsyncTask<ResultListener, Void, Void> {

     ResultListener listener;

        @Override
        protected Void doInBackground(ResultListener... maps) {
            this.listener = maps[0];
            uploadData();
            return null;
        }

        protected void onPostExecute(Void v) {
            /*Do something after the task is complete*/
            simpleDialog.dismiss();
            // Notify back to calling program
            listener.onResultReceived();
        }

 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM