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

Ste*_*lla 338 android android-asynctask

我有这两节课.我的主要活动和扩展的一个AsyncTask,现在在我的主要活动,我需要从得到的结果OnPostExecute()AsyncTask.我怎样才能将结果传递给我的主要活动?

这是示例代码.

我的主要活动.

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

}
Run Code Online (Sandbox Code Playgroud)

这是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);

}       

}   
Run Code Online (Sandbox Code Playgroud)

Hel*_*miB 714

Easy:

  1. Create interface class, where String output is optional, or can be whatever variables you want to return.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. Go to your AsyncTask class, and declare interface AsyncResponse as a field :

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
    Run Code Online (Sandbox Code Playgroud)
  3. In your main Activity you need to 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.
       }
     }
    
    Run Code Online (Sandbox Code Playgroud)

UPDATE

我不知道这对你们很多人来说是如此的喜爱.所以这是简单易用的使用方法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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的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();

 }
Run Code Online (Sandbox Code Playgroud)

或者,再次在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.
    }
}
Run Code Online (Sandbox Code Playgroud)

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

提示:更改String output,String response和,以及String result不同的匹配类型,以获得不同的对象.

  • 完全写下所有这些,然后看到你的答案:)这是相同的想法!+1.这种方式也可以听到AsyncTask的结果! (16认同)
  • 对于所有获取空指针的人,将接口传递给asyncTask类构造函数,然后将其分配给变量,然后对该变量调用processfinish().供参考,请参阅接受asnwer.http://stackoverflow.com/questions/9963691/android-asynctask-sending-callbacks-to-ui (12认同)
  • 我得到nullpointer异常,因为委托设置为null,请清除它 (8认同)
  • 对于.net开发人员来说,可以使用AutoResetEvents来实现这一点,并且还有一个用于autoresetevents的java实现,但这更加清晰.顺便说一句,ProcessFinish线程安全吗? (2认同)
  • @Sunny你是对的...另外,我们必须为async.delegate = this初始化异步对象; 上班.. (2认同)
  • 只是旁注在AsyncTask类中创建一个监听器(Activity)的弱引用,并在post执行时检查是否为null以避免内存泄漏 (2认同)

qui*_*int 23

有几个选择:

  • AsyncTask班级嵌入你的Activity班级.假设您在多个活动中不使用相同的任务,这是最简单的方法.您的所有代码都保持不变,您只需将现有任务类移动到活动类中的嵌套类.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 为您创建一个自定义构造函数,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
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 只是要小心的是内部类的AsyncTask可以内存泄漏的来源,这里解释http://garena.github.io/blog/2014/09/10/android-memory-leaks/ (2认同)
  • 保持活动引用也是内存泄漏。回调方法远胜于此 (2认同)

Ars*_*had 16

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

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

public interface AsyncResponse {
    void processFinish(Object output);
}
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

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

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.." });


            }
        });

    }



}
Run Code Online (Sandbox Code Playgroud)

谢谢


Nic*_*u P 16

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

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

  • 这对我有所帮助.我尝试了其他方式,比如来自@HelmiB的答案,但我没有得到任何结果 (3认同)
  • 你能解释为什么这会帮助OP解决他们的问题吗? (2认同)

Rah*_*hul 9

这个答案可能会迟到,但我想在你Activity依赖的时候提几件事AsyncTask.这将有助于您防止崩溃和内存管理.正如上面已经提到的答案一样interface,我们也说它们是回调.他们将作为告密者工作,但从未在这些情况下发送引用Activityinterface总是使用引用.

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

在此输入图像描述

正如您所看到的,如果我们从AsyncTask一个强大的参考开始,那么在我们获取数据之前不能保证我们Activity/ Fragment将会活着,所以最好WeakReference在这些情况下使用,这也有助于内存管理,因为我们永远不会我们Activity当时的强烈参考将有资格在其失真后进行垃圾收集.

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

MyTaskInformer.java 接口将作为告密者.

public interface MyTaskInformer {

    void onTaskDone(String output);

}
Run Code Online (Sandbox Code Playgroud)

MySmallAsyncTask.javaAsyncTask做长时间运行的任务,将使用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

MainActivity.java这个类用于在这个类和这个强制方法上启动我的AsyncTask工具.interfaceoverride

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Aya*_*fov 6

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

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

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


小智 5

在你的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();
Run Code Online (Sandbox Code Playgroud)

}`