Làm cách nào để đưa kết quả của OnPostExecute () vào hoạt động chính vì AsyncTask là một lớp riêng biệt?


361

Tôi có hai lớp này. Hoạt động chính của tôi và Hoạt động mở rộng AsyncTask, Bây giờ trong Hoạt động chính của tôi, tôi cần nhận được kết quả từ OnPostExecute()trong AsyncTask. Làm cách nào tôi có thể vượt qua hoặc nhận kết quả cho Hoạt động chính của mình?

Đây là mã mẫu.

Hoạt động chính của tôi.

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

}

Đây là lớp 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);

}       

}   

Bạn có thể tạo một giao diện như HelmiB đã giải thích hoặc bạn có thể tạo một máy thu phát sóng cục bộ Bạn có thể xem triển khai thu hồi phát sóng mẫu tại đây wiki.workrame.com/android-local-broadcast-receiver
Bikesh M

Tại sao không sử dụng mẫu Observer?
JAAAY 17/03/2017

Câu trả lời:


750

Dễ dàng:

  1. Tạo interfacelớp, trong đó String outputlà tùy chọn hoặc có thể là bất kỳ biến nào bạn muốn trả về.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. Đi đến AsyncTasklớp của bạn và khai báo giao diện AsyncResponsedưới dạng một trường:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. Trong hoạt động chính của bạn, bạn cần phải implementsgiao diện 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.
       }
     }
    

CẬP NHẬT

Tôi không biết đây là một yêu thích của nhiều bạn. Vì vậy, đây là cách đơn giản và thuận tiện để sử dụng interface.

vẫn dùng như cũ interface. FYI, bạn có thể kết hợp điều này vào AsyncTasklớp.

trong AsyncTasklớp:

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

làm điều này trong Activitylớp học của bạn

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

 }

Hoặc, thực hiện lại giao diện trên Hoạt động

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.
    }
}

Như bạn có thể thấy 2 giải pháp ở trên, giải pháp thứ nhất và thứ ba, nó cần tạo phương thức processFinish, phương thức còn lại, phương thức nằm trong tham số người gọi. Thứ ba gọn gàng hơn vì không có lớp ẩn danh lồng nhau. Hi vọng điêu nay co ich

Mẹo : Thay đổi String output, String responseString resultcác loại khớp khác nhau để có được đối tượng khác nhau.


20
Hoàn toàn viết tất cả những điều đó lên và sau đó thấy câu trả lời của bạn :) Đây là suy nghĩ giống nhau! +1. Ngoài ra, theo cách này, nhiều thứ có thể lắng nghe kết quả của AsyncTask!
Roloc

8
Tôi nhận được ngoại lệ nullpulum vì đại biểu được đặt thành null, vui lòng làm rõ nó
Reyjohn

2
Chỉ cần một lưu ý cho các nhà phát triển .net, người ta có thể sử dụng AutoResetEvents để đạt được điều này và cũng có một triển khai java cho autoresetevents nhưng điều này sạch sẽ hơn nhiều. Nhân tiện, luồng ProcessFinish có an toàn không?
Syler

13
đối với tất cả những người đang nhận con trỏ null, hãy chuyển giao diện của bạn đến hàm tạo của lớp asyncTask, sau đó gán nó cho một biến và sau đó gọi processfinish () trên biến đó. Để tham khảo xem chấp nhận asnwer. stackoverflow.com/questions/9963691/ cường
Nắng

2
@Sunny bạn đúng ... đồng thời, chúng tôi phải khởi tạo đối tượng async cho async.delegate = this; để làm việc ..
Ninja_Coder

24

Có một vài tùy chọn:

  • Tổ AsyncTasklớp trong Activitylớp của bạn . Giả sử bạn không sử dụng cùng một nhiệm vụ trong nhiều hoạt động, đây là cách dễ nhất. Tất cả mã của bạn vẫn giữ nguyên, bạn chỉ cần di chuyển lớp nhiệm vụ hiện có thành một lớp lồng trong lớp hoạt động của bạn.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
  • Tạo một hàm tạo tùy chỉnh cho bạn AsyncTaskđể tham chiếu đến của bạn Activity. Bạn sẽ khởi tạo nhiệm vụ với một cái gì đó như 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
        ...
    }
    

Trong tùy chọn thứ hai: Tại sao phải trải qua nỗi đau của một nhà xây dựng và một trường nếu lớp không có static? Chỉ cần sử dụng bất kỳ fieldOrMethodtừ MyActivityhoặc MyActivity.this.fieldOrMethodnếu nó bị bóng.
TWiStErRob

@TWiStErRob Thứ hai giả định MyAsyncTaskkhông một lớp bên trong.
quietmint 23/2/2015

1
Ồ, xin lỗi, private/ protectedđối với các lớp cấp cao nhất không được phép, do đó tôi nghĩ rằng nó phải là một staticlớp không bên trong.
TWiStErRob

2
Chỉ cần cẩn thận rằng lớp bên trong AsyncTask có thể là một nguồn rò rỉ bộ nhớ như được giải thích ở đây garena.github.io/blog/2014/09/10/android-memory-leaks
Đánh dấu Pazon

2
Giữ một tham chiếu Activity cũng là một rò rỉ bộ nhớ. Cách tiếp cận gọi lại tốt hơn nhiều so với cách này
OneCricketeer

19

Tôi cảm thấy cách tiếp cận dưới đây là rất dễ dàng.

Tôi đã khai báo một giao diện cho cuộc gọi lại

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

Sau đó, tạo tác vụ không đồng bộ để đáp ứng tất cả các loại yêu cầu song song

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

}

Sau đó được gọi là tác vụ không đồng bộ khi nhấp vào nút trong Lớp hoạt động.

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


            }
        });

    }



}

Cảm ơn


17

Bạn có thể thử mã này trong lớp Chính của bạn. Điều đó làm việc cho tôi, nhưng tôi đã thực hiện các phương pháp theo cách khác

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

2
Bạn có thể giải thích tại sao điều này sẽ giúp OP với vấn đề của họ?
John Odom

3
Điều đó đã giúp tôi. Tôi đã thử theo cách khác như câu trả lời từ @HelmiB nhưng tôi không nhận được kết quả
Nicu P

Ok xin lỗi vì câu trả lời của tôi. Cô ấy cần gọi lớp AsyncTask, và sau đó để đặt một tham số cho cuộc gọi này. AsyncTask được xác định bởi 3 loại chung: 1 params (miền máy chủ hoặc param khác) 2 tiến trình (có thể bị hủy), 3 kết quả. Tất cả các loại này có thể là: JSONObject hoặc chuỗi hoặc bất kỳ loại dữ liệu nào. Khi bạn có lớp AsyncTask, bạn nên xác định nơi gửi dữ liệu. ví dụ: asyncTask.execute (" sampletargeturl.com"). get () ;
Nicu P

Khi sử dụng phương pháp này, tôi nhận được một cảnh báo trên Logcat: "Tôi / Biên đạo múa ﹕ Bỏ qua 50 khung hình! Ứng dụng có thể đang làm quá nhiều việc trên luồng chính của nó." Làm thế nào để đối phó với điều này? UI có bị đóng băng khi chờ trả lại từ AsyncTask không?
Huy Đỗ

@NicuP bạn có thể quên gọi execute(), xem câu trả lời của tôi, tôi đã thêm nhận xét ở đó. bạn có thể muốn kiểm tra câu trả lời cập nhật của tôi. hi vọng điêu nay co ich.
HelmiB

16

Câu trả lời này có thể bị trễ nhưng tôi muốn đề cập đến một vài điều khi bạn Activityphụ thuộc vào AsyncTask. Điều đó sẽ giúp bạn trong việc ngăn chặn sự cố và quản lý bộ nhớ. Như đã đề cập trong các câu trả lời ở trên đi cùng interface, chúng tôi cũng nói chúng gọi lại. Họ sẽ làm việc như một người cung cấp thông tin, nhưng không bao giờ gửi tài liệu tham khảo mạnh mẽActivity hoặc interfaceluôn sử dụng tài liệu tham khảo yếu trong những trường hợp đó.

Vui lòng tham khảo ảnh chụp màn hình bên dưới để tìm hiểu làm thế nào có thể gây ra vấn đề.

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy nếu chúng ta bắt đầu AsyncTaskvới một mạnh mẽ tham khảo thì không có gì bảo đảm rằng chúng tôi Activity/ Fragmentsẽ sống cho đến khi chúng có được dữ liệu, vì vậy nó sẽ là tốt hơn để sử dụng WeakReferencetrong những trường hợp và điều đó cũng sẽ giúp đỡ trong việc quản lý bộ nhớ như chúng ta sẽ không bao giờ giữ tài liệu tham khảo mạnh mẽ của chúng tôi Activitysau đó sẽ đủ điều kiện để thu gom rác sau khi bị biến dạng.

Kiểm tra đoạn mã dưới đây để tìm hiểu cách sử dụng WeakReference tuyệt vời -

MyTaskInformer.java Giao diện sẽ làm việc như một người cung cấp thông tin.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.javaAsyncTask để thực hiện tác vụ chạy dài, sẽ sử dụng 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.javaLớp này được sử dụng để bắt đầu AsyncTasktriển khai của tôi interfacetrên lớp overridenày và phương thức bắt buộc này.

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
Điều đó thật tuyệt! một điểm quan trọng không thể nhận thấy.
HasH

6

trong Oncreate của bạn ():

`

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

} `


6

Bạn có thể làm điều đó trong một vài dòng, chỉ cần ghi đè onPostExecute khi bạn gọi AsyncTask. Đây là một ví dụ cho bạn:

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

Tôi hy vọng nó đã giúp bạn, hạnh phúc mã hóa :)


Nó không làm việc cho tôi. Nó chỉ không nhập vào onPostExecutephương thức.
Francisco Romero

4

Tại sao mọi người làm cho nó rất khó.

Điều này là đủ.

Không triển khai onPostExecute trên tác vụ async, thay vào đó hãy triển khai nó trên 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");

}


}

Điều này làm việc cho tôi. Nó là đơn giản và dễ hiểu nhất. Tôi nghĩ rằng nó đang sử dụng những gì Java được thiết kế để làm. Cảm ơn. PS: Có cần thiết phải thêm @Overridekhông?
Geezer cũ

1
Số @Override chỉ là một chú thích. Vì vậy, bạn đang nói với trình biên dịch java rằng bạn đang có ý định ghi đè phương thức và được thông báo nếu bạn không làm như vậy.
bugdayci

4

Bạn có thể gọi get()phương thức AsyncTask(hoặc quá tải get(long, TimeUnit)). Phương thức này sẽ chặn cho đến khi AsyncTaskhoàn thành công việc của nó, tại thời điểm đó, nó sẽ trả lại cho bạn Result.

Sẽ là khôn ngoan khi thực hiện các công việc khác giữa việc tạo / bắt đầu tác vụ không đồng bộ của bạn và gọi getphương thức, nếu không, bạn không sử dụng tác vụ async rất hiệu quả.


1
Downvote vecause get () sẽ chặn luồng chính. Không có lý do để sử dụng AsyncTask nếu nó sẽ chặn
GabrielBB

3

Bạn có thể viết người nghe của riêng bạn. Nó giống như câu trả lời của HelmiB nhưng trông tự nhiên hơn:

Tạo giao diện người nghe:

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

Sau đó viết tác vụ không đồng bộ của bạn:

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

Cuối cùng thực hiện trình nghe trong hoạt động:

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

Và đây là cách bạn có thể gọi 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...
}

2

Xin chào, bạn có thể làm một cái gì đó như thế này:

  1. Tạo lớp thực hiện 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");
            }
        }
    }
  2. Thêm vào hoạt động chính

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

1

Tạo một thành viên tĩnh trong lớp Activity của bạn. Sau đó gán giá trị trongonPostExecute

Ví dụ: nếu kết quả AsyncTask của bạn là Chuỗi, hãy tạo chuỗi tĩnh công khai trong Hoạt động của bạn

public static String dataFromAsyncTask;

Sau đó, trong onPostExecuteAsyncTask, chỉ cần thực hiện một cuộc gọi tĩnh đến lớp chính của bạn và đặt giá trị.

MainActivity.dataFromAsyncTask = "result blah";


1
các khả năng rò rỉ bộ nhớ trong kịch bản này là gì?
antroid

0

Tôi làm cho nó hoạt động bằng cách sử dụng luồng và xử lý / tin nhắn. Các bước như sau: Khai báo hộp thoại tiến trình

ProgressDialog loadingdialog;

Tạo một chức năng để đóng hộp thoại khi hoạt động kết thúc.

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

    }
    };

Mã chi tiết thực thi của bạn:

 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

Bạn cần sử dụng "giao thức" để ủy quyền hoặc cung cấp dữ liệu cho AsynTask.

Đại biểu và nguồn dữ liệu

Đại biểu là một đối tượng hành động thay mặt hoặc phối hợp với một đối tượng khác khi đối tượng đó gặp một sự kiện trong chương trình. ( Định nghĩa của Apple )

giao thức là các giao diện xác định một số phương thức để ủy thác một số hành vi.

Dưới đây là một ví dụ hoàn chỉnh !!!


0

thử cái này:

public class SomAsyncTask extends AsyncTask<String, Integer, JSONObject> {

    private CallBack callBack;

    public interface CallBack {
        void async( JSONObject jsonResult );
        void sync( JSONObject jsonResult );
        void progress( Integer... status );
        void cancel();
    }

    public SomAsyncTask(CallBack callBack) {
        this.callBack = callBack;
    }

    @Override
    protected JSONObject doInBackground(String... strings) {

        JSONObject dataJson = null;

        //TODO query, get some dataJson

        if(this.callBack != null)
            this.callBack.async( dataJson );// asynchronize with MAIN LOOP THREAD

        return dataJson;

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        if(this.callBack != null)
            this.callBack.progress(values);// synchronize with MAIN LOOP THREAD

    }

    @Override
    protected void onPostExecute(JSONObject jsonObject) {
        super.onPostExecute(jsonObject);

        if(this.callBack != null)
            this.callBack.sync(jsonObject);// synchronize with MAIN LOOP THREAD
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();

        if(this.callBack != null)
            this.callBack.cancel();

    }
}

Và ví dụ sử dụng:

public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         final Context _localContext = getContext();
         SomeAsyncTask.CallBack someCallBack = new SomeAsyncTask.CallBack() {

                @Override
                public void async(JSONObject jsonResult) {//async thread
                    //some async process, e.g. send data to server...
                }

                @Override
                public void sync(JSONObject jsonResult) {//sync thread
                    //get result...

                    //get some resource of Activity variable...
                    Resources resources = _localContext.getResources();
                }

                @Override
                public void progress(Integer... status) {//sync thread
                    //e.g. change status progress bar...
                }

                @Override
                public void cancel() {

                }

            };

            new SomeAsyncTask( someCallBack )
                                .execute("someParams0", "someParams1", "someParams2");

    }

0

Có lẽ sẽ quá nhiệt tình một chút nhưng tôi đã cung cấp các cuộc gọi lại cho cả mã thực thi và kết quả. rõ ràng để đảm bảo an toàn cho luồng, bạn muốn cẩn thận với những gì bạn truy cập trong cuộc gọi lại thực hiện.

Việc triển khai AsyncTask:

public class AsyncDbCall<ExecuteType,ResultType> extends AsyncTask<ExecuteType, Void,  
ResultType>
{
    public interface ExecuteCallback<E, R>
    {
        public R execute(E executeInput);
    }
    public interface PostExecuteCallback<R>
    {
        public void finish(R result);
    }

    private PostExecuteCallback<ResultType> _resultCallback = null;
    private ExecuteCallback<ExecuteType,ResultType> _executeCallback = null;


    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback, PostExecuteCallback<ResultType> postExecuteCallback)
    {
        _resultCallback = postExecuteCallback;
        _executeCallback = executeCallback;
    }

    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback)
    {
        _executeCallback = executeCallback;
    }

    @Override
    protected ResultType doInBackground(final ExecuteType... params)
    {
        return  _executeCallback.execute(params[0]);
    }

    @Override
    protected void onPostExecute(ResultType result)
    {
        if(_resultCallback != null)
            _resultCallback.finish(result);
    }
}

Một cuộc gọi lại:

 AsyncDbCall.ExecuteCallback<Device, Device> updateDeviceCallback = new 
 AsyncDbCall.ExecuteCallback<Device, Device>()
    {
        @Override
        public Device execute(Device device)
        {
            deviceDao.updateDevice(device);
            return device;
        }
    };

Và cuối cùng thực hiện tác vụ async:

 new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);

0

Hy vọng bạn đã thông qua điều này , nếu không xin vui lòng đọc.

https://developer.android.com/reference/android/os/AsyncTask

Tùy thuộc vào bản chất của dữ liệu kết quả, bạn nên chọn tùy chọn tốt nhất có thể bạn có thể nghĩ đến.

Đó là một lựa chọn tuyệt vời để sử dụng Giao diện

một số tùy chọn khác sẽ là ..

  • Nếu lớp AsyncTask được định nghĩa bên trong chính lớp bạn muốn sử dụng kết quả. Sử dụng biến toàn cục tĩnh hoặc get () , hãy sử dụng nó từ lớp ngoài ( biến dễ bay hơi nếu cần). nhưng nên lưu ý về tiến trình AsyncTask hoặc ít nhất nên đảm bảo rằng nó đã hoàn thành nhiệm vụ và kết quả có sẵn thông qua phương thức biến / get () toàn cầu. bạn có thể sử dụng bỏ phiếu, onProTHERUpdate (Tiến trình ...) , đồng bộ hóa hoặc giao diện (Điều nào phù hợp nhất với bạn)

  • Nếu Kết quả tương thích với mục nhập sharedPreference hoặc được lưu dưới dạng tệp trong bộ nhớ, bạn có thể lưu nó ngay cả từ chính tác vụ nền và có thể sử dụng phương thức onPostExecute ()
    để được thông báo khi có kết quả kí ức.

  • Nếu chuỗi đủ nhỏ và sẽ được sử dụng khi bắt đầu một hoạt động. có thể sử dụng ý định ( putExtra () ) trong onPostExecute () , nhưng hãy nhớ rằng bối cảnh tĩnh không an toàn để xử lý.

  • Nếu có thể, bạn có thể gọi một phương thức tĩnh từ phương thức onPostExecute (), với kết quả là tham số của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.