Android的类具有子类的AsyncTask等待postExecute返回之前 [英] Android Class with sub-class AsyncTask wait for the postExecute before returning the value

查看:117
本文介绍了Android的类具有子类的AsyncTask等待postExecute返回之前的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在做的事情为我的项目,其中我创建了一个单独的类,将只处理的AsyncTask,并得到我通过了web服务的价值,这个类应该返回JSON响应为一个字符串。现在,我已经做到了这一点使用 taskName.execute()获得(); ,其中它会等待任务完成,但问题是,它也在等待任务显示屏幕布局之前完成。使我progressDialog无用并导致切换画面的延迟。这里是我的code现在:

有关使用的AsyncTask类:

 公共类UtilGetResponse {    上下文语境;
    地图hash_values​​ =新的HashMap();
    INT的DialogType;
    字符串响应;
    / *
        计划DialogTypes:
    * 0 - 标准请等待对话框
    * 1 - 进度对话框
    * 2 - 相机上传对话框
    * * /
    InputStream为= NULL;
    StringBuilder的string_builder = NULL;
    公共UtilGetResponse(地图值,上下文baseContext,整型){
        / *初始化类,并通过哈希值的参数* /
        上下文= baseContext;
        hash_values​​.putAll(值);
        =的DialogType型;
    }    公共字符串startTask(){
        // TODO CASE WHEN指定对话框类型基
        公用事业UTIL =新的应用程序();        如果(util.isOnline(上下文)){
            尝试{
                新UploaderTaskStandard()的execute()得到()。
            }赶上(InterruptedException的E){
                e.printStackTrace();
            }赶上(为ExecutionException E){
                e.printStackTrace();
            }
        }
        返回响应; //的响应只能说明曾经的全任务完成
    }
    公共类UploaderTaskStandard扩展的AsyncTask<地图,太虚,太虚> {
        ProgressDialog simpleDialog;        @覆盖
        在preExecute保护无效(){
            / *做一些异步任务开始前* /
            simpleDialog =新ProgressDialog(背景);
            simpleDialog.setMessage(请稍候);
            simpleDialog.show();
        }        @覆盖
        保护无效doInBackground(地图...地图){
            uploadData();
            返回null;
        }        保护无效onPostExecute(虚空V){
            / *做某事的任务完成后,* /
            simpleDialog.dismiss();
        }
    }    私人无效uploadData(){
        响应=空;
        字符串URL = hash_values​​.get(URL)的toString()代替(,%20)。; //获取URL为%20替换空间        //如果用户试图上载文件中使用此部分
        尝试{
            HttpClient的客户端=新DefaultHttpClient();
            HttpPost后=新HttpPost(URL);
            MultipartEntity mpEntity =新MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);                / *这将转换每个值送入各个部分每个键HashMap中* /
            设置设置= hash_values​​.entrySet();
            迭代器迭代器= set.iterator();                / *做一个循环传递一个字符串的所有数据* /
            而(iterator.hasNext()){
                Map.Entry的mapEntry =(Map.Entry的)iterator.next();
                字符串关键字=将String.valueOf(mapEntry.getKey());
                字符串值=将String.valueOf(mapEntry.getValue());                    / *这会检查是否传递的数据是一个URL,文件或一个简单的值* /
                如果(!keyword.equals(URL)){
                    如果(value.matches((。*)/(。*))){
                        档案文件=新的文件(值);
                        Log.v(?这是否存在,将String.valueOf(file.exists()));
                        如果(file.exists()){
                            FileBody upload_file;
                            upload_file =新FileBody(文件);
                                / *不URL,但文件* /
                            mpEntity.addPart(关键字,upload_file);
                        }其他{
                                / *没有网址,而不是文件* /
                            mpEntity.addPart(关键字,新StringBody(值));
                        }
                    }其他{
                            / *没有网址,而不是文件* /
                        mpEntity.addPart(关键字,新StringBody(值));
                    }
                }
            }            post.setEntity(mpEntity);
            HTT presponse响应= client.execute(岗位);
            HttpEntity resEntity = response.getEntity();            是= resEntity.getContent();
        }赶上(例外五){
            e.printStackTrace();
            响应=空;
        }        / *转换JSON字符串* /
        尝试{
            读者的BufferedReader =新的BufferedReader(新的InputStreamReader(是,ISO-8859-1),8);
            string_builder =新的StringBuilder();
            串行=0;            而((行= reader.readLine())!= NULL){
                string_builder.append(行+\\ n);
            }
            is.close();
            响应= string_builder.toString();
        }赶上(例外五){
            e.printStackTrace();
        }    }}

和调用这个:

 地图hash_values​​ =新的HashMap();        尝试{
            HashMap的PARAMS =新的HashMap<字符串,字符串>();
            params.put(参数1,YOUR_PARAM);
            params.put(URL,YOUR_WEBSERVICE_URL);            //传递参数
            hash_values​​.putAll(PARAMS);
            //启动异步任务            UtilGetResponse UTIL =新UtilGetResponse(hash_values​​,getActivity(),0);
            字符串结果= util.startTask();            Log.v(结果字符串,结果);        }赶上(例外五){
            e.printStackTrace();
            e.getCause();
            Toast.makeText(getActivity(),哎呀问题,Toast.LENGTH_SHORT).show();
        }

时有一个办法,我正确地做到这一点没有真正等待整个任务移动到下一个屏幕前完成?我想用一个处理程序,但我不是如何无论如何使用它真正熟悉。


解决方案

您的问题是用这种用法

 新UploaderTaskStandard()的execute()获得();

虽然你使用AsynTask,但仍使系统等到的结果是对你的要求

,你需要的是一个传递机制,这会通知你回来一次结果准备就绪。你可以采取两种方法无论是。

 修改意见,并实现以下机制之一。
新UploaderTaskStandard()执行();


  1. 实施处理程序,并发布结果回来一次导致可用。

  2. 实现观察者设计模式,在那里你创建的方法,如 onResultReady 的接口,并通过实现上述接口的类的对象,以你的方法 startTask ,和张贴结果从AsyncTask的回 onPostExecute 一旦它通过接口提供的机制。

通过接口去会很简单,以这种方式code将独立网络的逻辑,样品code以下

  //观察者监听器接口设计
接口ResultListener {
    //你可以重载此方法,数据类型,你想返回
    公共无效onResultReceived();    //使用他们在一个适当的方式发送错误信息回程序
    公共无效onTaskCancelled();
    公共无效onerror的();}
 //这将是你的新方法签名
 公共字符串startTask(ResultListener监听){
     //调用它liske这一点,通过监听参考
     新UploaderTaskStandard()执行(监听);
 } //这是你的AsyncTask模型
 公共类UploaderTaskStandard扩展的AsyncTask< ResultListener,太虚,太虚> {     ResultListener监听;        @覆盖
        保护无效doInBackground(ResultListener ...地图){
            this.listener =地图[0];
            uploadData();
            返回null;
        }        保护无效onPostExecute(虚空V){
            / *做某事的任务完成后,* /
            simpleDialog.dismiss();
            //通知回调用程序
            listener.onResultReceived();
        } }

currently I'm doing something for my project wherein I created a separate Class that will only handle the Asynctask and get the value of the webservices I passed and that class should return the JSON response as a String. Now I already achieved it using taskName.execute().get(); wherein it will wait for the task to complete but the problem is it is also waiting for the task to complete before displaying the screen layout. Making my progressDialog useless and cause a delay on switching screens. Here's my code for now:

For the Class with 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();
        }

    }

}

And to call this:

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();
        }

Is there's a way for me to do this properly without really waiting for the whole task to finish before moving to the next screen? I'm thinking of using a Handler but I'm not really familiar on how to use it anyway.

解决方案

Your issue is with usage of this

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

Although you using AsynTask, but still making system wait until result which is against your requirement, what you need is a delivery mechanism, which will notify you back once results are ready. You can take either of two approaches.

change to this, and implement one of below mechanism.
new UploaderTaskStandard().execute();

  1. Implementing handler, and posting result back once result available.
  2. Implementing observer design pattern, where you create an interface with methods such as onResultReady, and passing an object of class implementing above interface to your method startTask, and posting result back from AsyncTask onPostExecute once it is available via interface mechanism.

Going via interface will be very easy and in this way your code will be independent of your network logic, sample code below

// 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();
        }

 }

这篇关于Android的类具有子类的AsyncTask等待postExecute返回之前的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆