首页 文章

如何将OnPostExecute()的结果导入主活动,因为AsyncTask是一个单独的类?

提问于
浏览
307

我有这两节课 . 我的主要Activity和扩展 AsyncTask 的那个,现在在我的主Activity中我需要从 AsyncTask 中的 OnPostExecute() 获得结果 . 如何将结果传递给我的主要活动?

这是示例代码 .

我的主要活动 .

public class MainActivity extends Activity{

    AasyncTask asyncTask = new AasyncTask();

    @Override
    public void onCreate(Bundle aBundle) {
        super.onCreate(aBundle);            

        //Calling the AsyncTask class to start to execute.  
        asyncTask.execute(a.targetServer); 

        //Creating a TextView.
        TextView displayUI = asyncTask.dataDisplay;
        displayUI = new TextView(this);
        this.setContentView(tTextView); 
    }

}

这是AsyncTask类

public class AasyncTask extends AsyncTask<String, Void, String> {

TextView dataDisplay; //store the data  
String soapAction = "http://sample.com"; //SOAPAction header line. 
String targetServer = "https://sampletargeturl.com"; //Target Server.

//SOAP Request.
String soapRequest = "<sample XML request>";    



@Override
protected String doInBackground(String... string) {

String responseStorage = null; //storage of the response

try {


    //Uses URL and HttpURLConnection for server connection. 
    URL targetURL = new URL(targetServer);
    HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setDoInput(true);
    httpCon.setUseCaches(false); 
    httpCon.setChunkedStreamingMode(0);

    //properties of SOAPAction header
    httpCon.addRequestProperty("SOAPAction", soapAction);
    httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8"); 
    httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
    httpCon.setRequestMethod(HttpPost.METHOD_NAME);


    //sending request to the server.
    OutputStream outputStream = httpCon.getOutputStream(); 
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(soapRequest);
    writer.flush();
    writer.close();


    //getting the response from the server
    InputStream inputStream = httpCon.getInputStream(); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);

    int intResponse = httpCon.getResponseCode();

    while ((intResponse = bufferedReader.read()) != -1) {
        byteArrayBuffer.append(intResponse);
    }

    responseStorage = new String(byteArrayBuffer.toByteArray()); 

    } catch (Exception aException) {
    responseStorage = aException.getMessage(); 
    }
    return responseStorage;
}

protected void onPostExecute(String result) {

    aTextView.setText(result);

}       

}

14 回答

  • 1

    这个答案可能会迟到,但是当你的 Activity 依赖于 AsyncTask 时,我想提一些事情 . 这将有助于您防止崩溃和内存管理 . 正如上面提到的答案中提到的 interface ,我们也说它们是回调 . 它们将作为线人工作,但在这些情况下,永远不会发送 Activityinterfacestrong 引用始终使用 weak 引用 .

    请参阅下面的屏幕截图,了解这可能导致的问题 .

    正如您所看到的,如果我们使用 strong 引用启动 AsyncTask ,则无法保证我们的 Activity / Fragment 在我们获取数据之前将处于活动状态,因此在这些情况下使用 WeakReference 会更好,这也有助于内存管理我们永远不会持有我们的 Activity 的强大参考,然后它会在失真后有资格进行垃圾收集 .

    检查下面的代码片段,了解如何使用真棒WeakReference -

    MyTaskInformer.java 将作为线人工作的接口 .

    public interface MyTaskInformer {
    
        void onTaskDone(String output);
    
    }
    

    MySmallAsyncTask.java AsyncTask做长时间运行的任务,它将使用 WeakReference .

    public class MySmallAsyncTask extends AsyncTask<String, Void, String> {
    
        // ***** Hold weak reference *****
        private WeakReference<MyTaskInformer> mCallBack;
    
        public MySmallAsyncTask(MyTaskInformer callback) {
            this.mCallBack = new WeakReference<>(callback);
        }
    
        @Override
        protected String doInBackground(String... params) {
    
            // Here do whatever your task is like reading/writing file
            // or read data from your server or any other heavy task
    
            // Let us suppose here you get response, just return it
            final String output = "Any out, mine is just demo output";
    
            // Return it from here to post execute
            return output;
        }
    
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
    
            // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask
    
            // Make sure your caller is active
    
            final MyTaskInformer callBack = mCallBack.get();
    
            if(callBack != null) {
                callBack.onTaskDone(s);
            }
        }
    }
    

    MainActivity.java 此类用于在此类上启动 AsyncTask 实现 interface ,并使用 override 此强制方法 .

    public class MainActivity extends Activity implements MyTaskInformer {
    
        private TextView mMyTextView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mMyTextView = (TextView) findViewById(R.id.tv_text_view);
    
            // Start your AsyncTask and pass reference of MyTaskInformer in constructor
            new MySmallAsyncTask(this).execute();
        }
    
        @Override
        public void onTaskDone(String output) {
    
            // Here you will receive output only if your Activity is alive.
            // no need to add checks like if(!isFinishing())
    
            mMyTextView.setText(output);
        }
    }
    
  • 2

    简单:

    • 创建 interface 类,其中 String output 是可选的,或者可以是您想要返回的任何变量 .
    public interface AsyncResponse {
        void processFinish(String output);
    }
    
    • 转到 AsyncTask 类,并将接口 AsyncResponse 声明为字段:
    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
    • 在您的主要活动中,您需要 implements interface AsyncResponse .
    public class MainActivity implements AsyncResponse{
      MyAsyncTask asyncTask =new MyAsyncTask();
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
    
         //this to set delegate/listener back to this class
         asyncTask.delegate = this;
    
         //execute the async task 
         asyncTask.execute();
      }
    
      //this override the implemented method from asyncTask
      @Override
      void processFinish(String output){
         //Here you will receive the result fired from async class 
         //of onPostExecute(result) method.
       }
     }
    

    UPDATE

    我没有't know this is such a favourite to many of you. So here'使用 interface 的简单方便的方法 .

    仍然使用相同的 interface . 仅供参考,您可以将其合并到 AsyncTask 课程中 .

    AsyncTask 类:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
    
      // you may separate this or combined to caller class.
      public interface AsyncResponse {
            void processFinish(String output);
      }
    
      public AsyncResponse delegate = null;
    
        public MyAsyncTask(AsyncResponse delegate){
            this.delegate = delegate;
        }
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
    }
    

    Activity 课程中执行此操作

    public class MainActivity extends Activity {
    
       MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse(){
    
         @Override
         void processFinish(String output){
         //Here you will receive the result fired from async class 
         //of onPostExecute(result) method.
         }
      }).execute();
    
     }
    

    或者,再次在Activity上实现接口

    public class MainActivity extends Activity 
        implements AsyncResponse{
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
            //execute the async task 
            new MyAsyncTask(this).execute();
        }
    
        //this override the implemented method from AsyncResponse
        @Override
        void processFinish(String output){
            //Here you will receive the result fired from async class 
            //of onPostExecute(result) method.
        }
    }
    

    正如你可以看到上面的第一个和第三个解决方案,它需要创建方法 processFinish ,另一个,方法在调用者参数内 . 第三个更整洁,因为没有嵌套的匿名类 . 希望这可以帮助

    Tip :将 String outputString responseString result 更改为不同的匹配类型以获取不同的对象 .

  • 4

    您可以在Main类中尝试此代码 . 这对我有用,但我已经用其他方式实现了方法

    try {
        String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
    } 
    catch (ExecutionException | InterruptedException ei) {
        ei.printStackTrace();
    }
    
  • 5

    你可以编写自己的监听器 . 它与HelmiB的答案相同,但看起来更自然:

    创建监听器接口:

    public interface myAsyncTaskCompletedListener {
        void onMyAsynTaskCompleted(int responseCode, String result);
    }
    

    然后编写异步任务:

    public class myAsyncTask extends AsyncTask<String, Void, String> {
    
        private myAsyncTaskCompletedListener listener;
        private int responseCode = 0;
    
        public myAsyncTask() {
        }
    
        public myAsyncTask(myAsyncTaskCompletedListener listener, int responseCode) {
            this.listener = listener;
            this.responseCode = responseCode;
        }
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
    
    
        @Override
        protected String doInBackground(String... params) {
            String result;
            String param = (params.length == 0) ? null : params[0];
            if (param != null) {
                // Do some background jobs, like httprequest...
                return result;
            }
            return null;
        }
    
        @Override
        protected void onPostExecute(String finalResult) {
            super.onPostExecute(finalResult);
            if (!isCancelled()) {
                if (listener != null) {
                    listener.onMyAsynTaskCompleted(responseCode, finalResult);
                }
            }
        }
    }
    

    最后在activity中实现监听器:

    public class MainActivity extends AppCompatActivity implements myAsyncTaskCompletedListener {
    
        @Override
        public void onMyAsynTaskCompleted(int responseCode, String result) {
    
            switch (responseCode) {
                case TASK_CODE_ONE: 
                    // Do something for CODE_ONE
                    break;
                case TASK_CODE_TWO:
                    // Do something for CODE_TWO
                    break;
                default: 
                    // Show some error code
            }        
        }
    

    这就是你可以调用asyncTask的方法:

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // Some other codes...
            new myAsyncTask(this,TASK_CODE_ONE).execute("Data for background job");
            // And some another codes...
    }
    
  • 6

    我通过使用线程和处理程序/消息使其工作 . 步骤如下:声明进度对话框

    ProgressDialog loadingdialog;
    

    操作完成后,创建一个关闭对话框的功能 .

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            loadingdialog.dismiss();
    
        }
        };
    

    编写执行细节:

    public void startUpload(String filepath) {
        loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
        final String _path = filepath;
        new Thread() {
            public void run() {
                try {
                    UploadFile(_path, getHostName(), getPortNo());
                    handler.sendEmptyMessage(0);
    
                } catch (Exception e) {
                    Log.e("threadmessage", e.getMessage());
                }
            }
        }.start();
    }
    
  • 0

    在Activity类中创建一个静态成员 . 然后在 onPostExecute 期间分配值

    例如,如果AsyncTask的结果是String,请在Activity中创建一个公共静态字符串

    public static String dataFromAsyncTask;

    然后,在AsyncTask的 onPostExecute 中,只需对主类进行静态调用并设置值 .

    MainActivity.dataFromAsyncTask = "result blah";

  • 660

    有几个选择:

    • AsyncTask 类嵌套在 Activity 类中 . 假设你没有't use the same task in multiple activities, this is the easiest way. All your code stays the same, you just move the existing task class to be a nested class inside your activity'的课程 .
    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
    • AsyncTask 创建一个自定义构造函数,该构造函数引用您的 Activity . 您可以使用 new MyAsyncTask(this).execute(param1, param2) 之类的东西来实例化任务 .
    public class MyAsyncTask extends AsyncTask<String, Void, String> {
        private Activity activity;
    
        public MyAsyncTask(Activity activity) {
            this.activity = activity;
        }
    
        // existing AsyncTask code
        ...
    }
    
  • 14

    嗨,你可以做这样的事情:

    • 创建实现AsyncTask的类
    // TASK 
    public class SomeClass extends AsyncTask<Void, Void, String>>
    {
    
        private OnTaskExecutionFinished _task_finished_event;
    
        public interface OnTaskExecutionFinished
        {
            public void OnTaskFihishedEvent(String Reslut);
        }
    
        public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event)
        {
            if(_event != null)
            {
                this._task_finished_event = _event;
            }
        }
    
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
    
        }
    
        @Override
        protected String doInBackground(Void... params)
        {
            // do your background task here ...
    
            return "Done!";
        }
    
        @Override
        protected void onPostExecute(String result)
        {
            super.onPostExecute(result);
            if(this._task_finished_event != null)
            {
                this._task_finished_event.OnTaskFihishedEvent(result);
            }
            else
            {
                Log.d("SomeClass", "task_finished even is null");
            }
        }
    }
    
    • 添加主要活动
    // MAIN ACTIVITY
    public class MyActivity extends ListActivity
    {
       ...
        SomeClass _some_class = new SomeClass();
        _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished()
        {
        @Override
        public void OnTaskFihishedEvent(String result)
        {
            Toast.makeText(getApplicationContext(),
                    "Phony thread finished: " + result,
                    Toast.LENGTH_SHORT).show();
        }
    
       });
       _some_class.execute();
       ...
     }
    
  • 0

    在你的Oncreate()中:

    `

    myTask.execute("url");
    String result = "";
    try {
          result = myTask.get().toString();
    } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
    }catch (ExecutionException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
    

    }`

  • 3

    为什么人们会如此努力 .

    这应该足够了 .

    不要在异步任务上实现onPostExecute,而是在Activity上实现它:

    public class MainActivity extends Activity 
    {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
    
        //execute the async task 
        MyAsyncTask task = new MyAsyncTask(){
                protected void onPostExecute(String result) {
                    //Do your thing
                }       
    
        }
    
        task.execute("Param");
    
    }
    
    
    }
    
  • 2

    您需要使用 "protocols" 委托或向 AsynTask 提供数据 .

    Delegates and Data Sources

    委托是一个对象,当该对象遇到程序中的事件时,该对象代表另一个对象或与另一个对象协同工作 . (Apple definition

    protocols are interfaces that define some methods to delegate some behaviors.

    Here is a complete example!!!

  • 5

    我觉得下面的方法非常简单 .

    我已经声明了一个回调接口

    public interface AsyncResponse {
        void processFinish(Object output);
    }
    

    然后创建异步任务以响应所有类型的并行请求

    public class MyAsyncTask extends AsyncTask<Object, Object, Object> {
    
        public AsyncResponse delegate = null;//Call back interface
    
        public MyAsyncTask(AsyncResponse asyncResponse) {
            delegate = asyncResponse;//Assigning call back interfacethrough constructor
        }
    
        @Override
        protected Object doInBackground(Object... params) {
    
          //My Background tasks are written here
    
          return {resutl Object}
    
        }
    
        @Override
        protected void onPostExecute(Object result) {
            delegate.processFinish(result);
        }
    
    }
    

    然后单击活动类中的按钮时调用异步任务 .

    public class MainActivity extends Activity{
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
        Button mbtnPress = (Button) findViewById(R.id.btnPress);
    
        mbtnPress.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
    
                    MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {
    
                        @Override
                        public void processFinish(Object output) {
                            Log.d("Response From Asynchronous task:", (String) output);
    
                            mbtnPress.setText((String) output);
                       }
                    });
    
                    asyncTask.execute(new Object[] { "Your request to aynchronous task class is giving here.." });
    
    
                }
            });
    
        }
    
    
    
    }
    

    谢谢

  • 13

    您可以调用 AsyncTaskget()方法(或重载的get(long, TimeUnit)) . 这种方法会阻止直到 AsyncTask 完成其工作,此时它将返回 Result .

    在创建/启动异步任务和调用 get 方法之间进行其他工作是明智的,否则您不会非常有效地利用异步任务 .

  • 23

    您可以在几行中完成,只需在调用AsyncTask时重写onPostExecute . 这是一个例子:

    new AasyncTask()
    {
        @Override public void onPostExecute(String result)
        {
           // do whatever you want with result 
        }
    }.execute(a.targetServer);
    

    我希望它能帮助你,快乐的编码:)

相关问题