itsource

Android의 AsyncTask에서 값 반환

mycopycode 2022. 11. 24. 20:47
반응형

Android의 AsyncTask에서 값 반환

한 가지 간단한 질문입니다.다음에서 값을 반환할 수 있습니까?AsyncTask?

//AsyncTask is a member class
private class MyTask extends AsyncTask<Void, Void, Void>{

    protected Void doInBackground(Void... params) {
         //do stuff
         return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        //do stuff
        //how to return a value to the calling method?
    }
}

그리고 내 안에서Activity/Fragment:

// The task is started from activity
myTask.execute()
// something like this?
myvalue = myTask.getvalue() 

편집: Java에 익숙하지 않은 곳이 어디냐는 질문을 오래 전에 받았습니다.이제 Java에 익숙해졌으니 간단히 요약해 보겠습니다.

비동기 태스크의 포인트는 태스크가asynchronous즉, 콜 후에execute()태스크에서 태스크는 자체 스레드에서 실행되기 시작합니다. 원래 호출 스레드가 이미 다른 작업을 수행했기 때문에 비동기 태스크에서 값을 반환하는 것은 무의미합니다(태스크가 비동기 작업인 경우).

시간을 생각해 보세요.기본 스레드와 병렬로 실행되는 태스크를 시작했습니다.병렬 실행 작업이 완료되면 메인 스레드에서도 시간이 경과한 것입니다.병렬 태스크는 기본 스레드에 값을 반환하기 위해 과거로 돌아갈 수 없습니다.

저는 C에서 왔기 때문에 잘 몰랐습니다.하지만 많은 사람들이 같은 질문을 하고 있는 것 같아서 좀 더 명확히 해두려고 했어요.

그래서 하는 거야.UI 스레드에서 실행되며, 여기서 화면(또는 필요한 곳)으로 결과를 전달할 수 있습니다.최종 결과가 나올 때까지 호출되지 않습니다.중간 결과를 가져오려면 다음을 참조하십시오.

값을 처리하는 메서드를 호출하면 어떨까요?

public class MyClass extends Activity {

    private class myTask extends AsyncTask<Void, Void, Void> {

        //initiate vars
        public myTask() {
            super();
            //my params here
        }

        protected Void doInBackground(Void... params) {
            //do stuff
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            //do stuff
            myMethod(myValue);
        }
    }

    private myHandledValueType myMethod(Value myValue) {
        //handle value 
        return myHandledValueType;
    }
}

가장 쉬운 방법은 (필요에 따라 작성 시) 발신 객체를 비동기 태스크에 전달하는 것입니다.

public class AsyncGetUserImagesTask extends AsyncTask<Void, Void, Void> {

    private MyImagesPagerFragment mimagesPagerFragment;
    private ArrayList<ImageData> mImages = new ArrayList<ImageData>();

    public AsyncGetUserImagesTask(MyImagesPagerFragment imagesPagerFragment) {
        this.mimagesPagerFragment = imagesPagerFragment;
    }

    @Override
    public Void doInBackground(Void... records) {
        // do work here
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        mimagesPagerFragment.updateAdapter(mImages);
    }
}

또한 콜링 클래스(액티비티 또는 프래그먼트)에서 다음 작업을 수행합니다.

public class MyImagesPagerFragment extends Fragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        AsyncGetUserImagesTask mGetImagesTask = new AsyncGetUserImagesTask(this);
        mGetImagesTask.execute();
    }

그리고 온포스트ExecuteMethod는 원하는 원래 클래스의 메서드를 호출합니다.다음은 예를 제시하겠습니다.

    public void updateAdapter(List<ImageData> images) {
        mImageAdapter.setImages(images);
        mImageAdapter.notifyDataSetChanged();
    }
}

코드 예:액티비티는 AsyncTask를 사용하여 백그라운드스레드의 값을 취득한 후 AsyncTask는 processValue를 호출하여 결과를 Activity로 되돌립니다.

public class MyClass extends Activity {
  private void getValue() {
      new MyTask().execute();
  }

  void processValue(Value myValue) {
     //handle value 
     //Update GUI, show toast, etc..
  }

  private class MyTask extends AsyncTask<Void, Void, Value> {
    @Override
    protected Value doInBackground(Void... params) {
      //do stuff and return the value you want 
      return Value;
    }

    @Override
    protected void onPostExecute(Value result) {
      // Call activity method with results
      processValue(result);
    }
  }
}

다음 것을 시도해 보십시오.myvalue = new myTask().execute().get();- 비동기론이 종료되지 않을 때까지 프로세스를 정지합니다.

'프로토콜'을 사용하여 데이터를 위임 또는 제공해야 합니다.AsynTask.

딜러와 데이터 소스

위임자는 프로그램에서 다른 개체가 이벤트를 만났을 때 해당 개체를 대신하거나 해당 개체와 함께 작업하는 개체입니다.(Apple 정의)

프로토콜은 일부 동작을 위임하는 방법을 정의하는 인터페이스입니다.


딜러: 백그라운드 스레드의 객체에서 이벤트를 캡처합니다.


비동기 태스크:

public final class TaskWithDelegate extends AsyncTask<..., ..., ...> {
    //declare a delegate with type of protocol declared in this task
    private TaskDelegate delegate;

    //here is the task protocol to can delegate on other object
    public interface TaskDelegate {
        //define you method headers to override
        void onTaskEndWithResult(int success);
        void onTaskFinishGettingData(Data result);
    }

    @Override
    protected Integer doInBackground(Object... params) {
        //do something in background and get result
        if (delegate != null) {
            //return result to activity
            delegate.onTaskFinishGettingData(result);
        }   
    }

    @Override
    protected void onPostExecute(Integer result) {
        if (delegate != null) {
            //return success or fail to activity
            delegate.onTaskEndWithResult(result);
        }   
    }
}

액티비티:

public class DelegateActivity extends Activity implements TaskDelegate {
    void callTask () {
            TaskWithDelegate task = new TaskWithDelegate;
        //set the delegate of the task as this activity
        task.setDelegate(this);
    }

    //handle success or fail to show an alert...
    @Override
    void onTaskEndWithResult(int success) {

    }

    //handle data to show them in activity...
    @Override
    void onTaskFinishGettingData(Data result) {

    }
}

편집: doInBackground에서 대리인을 호출하고 대리인이 일부 보기를 편집하려고 하면 메인 스레드에서만 보기를 조작할 수 있기 때문에 충돌합니다.


// this refers to Activity
this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
    // Here you can edit views when task notify some changes from background thread
        textView.setText(someValue);
    }
});

추가의

DATASOURCE: 백그라운드 스레드의 개체에 데이터 제공


비동기 태스크:

public final class TaskWithDataSource extends AsyncTask<..., ..., ...> {
    //declare a datasource with type of protocol declared in this task
    private TaskDataSource dataSource;
    private Object data;

    //here is the task protocol to can provide data from other object
    public interface TaskDataSource {
        //define you method headers to override
        int indexOfObject(Object object);
        Object objectAtIndex(int index);
    }

    @Override
    protected void onPreExecute(Integer result) {
        if (dataSource != null) {
            //ask for some data
            this.data = dataSource.objectAtIndex(0);
        }   
    }

    @Override
    protected Integer doInBackground(Object... params) {
        //do something in background and get result
        int index;
        if (dataSource != null) {
            //ask for something more
            index = dataSource.indexOfObject(this.data);
        }   
    }
}

액티비티:

public class DataSourceActivity extends Activity implements TaskDataSource {
    void callTask () {
            TaskWithDataSource task = new TaskWithDataSource;
        //set the datasource of the task as this activity
        task.setDataSource(this);
    }

    //send some data to the async task when it is needed...
    @Override
    Object objectAtIndex(int index) {
        return new Data(index);
    }

    //send more information...
    @Override
    int indexOfObject(Object object) {
        return new object.getIndex();
    }
}

범용 파라미터 사용

AsyncTask<Params, Progress, Result>
  • Params 유형: " " " "
  • Progress 상황을 - "진행 상황"
  • Result 유형: " " " "

라고 생각하다

Result = task(Params)

★★YourObject " " " URL:

new AsyncTask<String, Void, YourObject>()
{
    @Override
    protected void onPreExecute()
    {
        /* Called before task execution; from UI thread, so you can access your widgets */

        // Optionally do some stuff like showing progress bar
    };

    @Override
    protected YourObject doInBackground(String... url)
    {
        /* Called from background thread, so you're NOT allowed to interact with UI */

        // Perform heavy task to get YourObject by string
        // Stay clear & functional, just convert input to output and return it
        YourObject result = callTheServer(url);
        return result;
    }

    @Override
    protected void onPostExecute(YourObject result)
    {
        /* Called once task is done; from UI thread, so you can access your widgets */

        // Process result as you like
    }
}.execute("http://www.example.com/");

AsyncTask에서 결과를 얻으려면 다음 작업을 수행해야 합니다.super.onPostExcecute(result)이는 백그라운드 및 비동기 태스크도 완료되었음을 의미하기 때문입니다.예를 들어 다음과 같습니다.

... into your async task

@Override
protected void onPostExecute(MyBeanResult result) {
    if (dialog.isShowing()) {
        dialog.dismiss();
    }
    if (mWakeLock.isHeld()) {
        mWakeLock.release();
    }
    super.onPostExecute(result);
    MyClassName.this.checkResponseForIntent(result);
}

methodr checkResponseFor 및의도는 다음과 같습니다.

private void checkResponseForIntent(MyBeanResult response) {
    if (response == null || response.fault != null) {
        noServiceAvailable();
        return;
    }
 ... or do what ever you want, even call an other async task...

이 기능을 사용하는 데 문제가 있었습니다..get()AsyncTask와 ProgressBar가 함께 사용할 수 없습니다.get()doInBackground를 사용합니다.

도움이 되길 바랍니다.

MainActivity 클래스를 Async 클래스로 전달하면 내부 클래스의 MainActivity 함수에 액세스 할 수 있습니다.이 방법은 문제 없습니다.

public class MainActivity extends ActionBarActivity {

   void callAsync()
   {
      Async as = new Async(this,12,"Test");
      as.execute();
   }

   public void ReturnThreadResult(YourObject result)
   {
     // TO DO:
     // print(result.toString());

   }
}


public class Async extends AsyncTask<String, String, Boolean> {
    MainActivity parent;
    int param1;
    String param2;

    public Async(MainActivity parent,int param1,String param2){
       this.parent = parent;
       this.param1 = param1;
       this.param2 = param2;
    }

    @Override
    protected void onPreExecute(){};

    @Override
    protected YourObject doInBackground(String... url)
    {
        return result;
    }

    @Override
    protected void onPostExecute(YourObject result)
    {
       // call an external function as a result 
       parent.ReturnThreadResult(result);
    }
  }  

언급URL : https://stackoverflow.com/questions/9458258/return-a-value-from-asynctask-in-android

반응형