代码之家  ›  专栏  ›  技术社区  ›  realtebo

安卓:如果AsyncTask在一个单独的类中,如何从AsyncTask更新UI?

  •  40
  • realtebo  · 技术社区  · 12 年前

    我讨厌内部阶级。

    我有一个主要活动,他启动了一个“短命”异步任务。

    异步任务是 在单独的文件中 ,不是主要活动的内部类

    我需要异步任务更新主活动中的textView。

    我知道如果AsyncTask是内部类,我可以从onProgressUpdate更新TextView

    但是,如何从外部的、独立的、异步的任务?

    更新:这看起来像在工作:

    在积极的时候,我称之为任务

    backgroundTask = new BackgroundTask(this);
    backgroundTask.execute();
    

    在构造函数中,我已经

    public BackgroundTask(Activity myContext)
    {
        debug = (TextView) myContext.findViewById(R.id.debugText);
    }
    

    其中debug是AsyncTask的私有字段。

    所以在ProgressUpdate上我可以

    debug.append(text);
    

    谢谢大家的建议

    7 回复  |  直到 12 年前
        1
  •  41
  •   Marcin Orlowski    5 年前

    AsyncTask总是与 Activity ,但我怀疑你的意思是它与你的活动类文件在不同的文件中,所以你不能从成为活动的内部类中受益。只需将活动上下文作为参数传递给异步任务(即其构造函数)

    class MyAsyncTask extends AsyncTask<URL, Integer, Long> {
    
        WeakReference<Activity> mWeakActivity;
    
        public MyAsyncTask(Activity activity) {
           mWeakActivity = new WeakReference<Activity>(activity);
        }
    
     ...
    

    并在需要时使用(记住不要在 doInBackground() )也就是说,当你通常打电话时

    int id = findViewById(...)
    

    在您调用的AsyncTask中,即。

    Activity activity = mWeakActivity.get();
    if (activity != null) {
       int id = activity.findViewById(...);
    }
    

    请注意,我们 活动 可以离开一段时间 doInBackground()中的操作 正在进行中(因此返回的引用可以变成 null ),但通过使用 WeakReference 我们并不阻止GC收集它(并泄漏内存),随着“活动”的消失,甚至尝试更新它的状态通常都是毫无意义的(尽管如此,根据您的逻辑,您可能想做一些事情,比如更改内部状态或更新DB,但必须跳过触摸UI)。

        2
  •  26
  •   Mateusz Piotrowski Reinstate Monica Please    8 年前

    使用接口 1) 创建一个接口

    public interface OnDataSendToActivity {
        public void sendData(String str);
    }
    

    2) 在您的活动中实施

    public class MainActivity extends Activity implements OnDataSendToActivity{
    
         @Override
         protected void onCreate(Bundle savedInstanceState) {
              new AsyncTest(this).execute(new String[]{"AnyData"}); // start your task
         }
    
         @Override
         public void sendData(String str) {
             // TODO Auto-generated method stub
    
         }
    
    }
    

    3) 在AsyncTask(活动活动)中创建构造函数{} 在AsyncTask文件中注册接口 并调用如下接口方法。

    public class AsyncTest extends AsyncTask<String, Integer, String> {
    
        OnDataSendToActivity dataSendToActivity;
        public AsyncTest(Activity activity){
            dataSendToActivity = (OnDataSendToActivity)activity;
        }
    
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            dataSendToActivity.sendData(result);
        }
    
    }
    

    在这里,您的OnPostExecute将在AsyncTask完成所有任务后调用,并将获得“结果” 作为参数,由doInBackground()返回{return“”;}。

    当“dataSendToActivity.sendData(result);”时,它将调用活动的重写方法“public void sendData(String str){}”。

    一个需要记住的边缘案例:一定要通过 this ,即您当前活动的上下文 AsyncTask 并且不要创建活动的另一个实例,否则 Activity 将被摧毁,并创建新的一个。

        3
  •  5
  •   Piyush Agarwal    12 年前

    在活动类中创建一个静态函数,在其中传递上下文以更新文本视图,然后在AsynkTask类中调用此函数进行更新。

    在活动类中: 公共静态void updateTextView(){

    //您的代码在这里 }

    在AynckTask类中调用此函数。

        4
  •  3
  •   Manfred Moser    12 年前

    只需在构造函数中将上下文(活动或其他)传递给AsyncTask,然后在onSuccess或onProgressUpdate中调用上下文上所需的任何内容。

        5
  •  3
  •   newbyca    12 年前

    我为这种场景编写了一个AsyncTask的小扩展。它允许您将AsyncTask保存在一个单独的类中,但也可以方便地访问Task的完成情况:

    public abstract class ListenableAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result>{
    
        @Override
        protected final void onPostExecute(Result result) {
            notifyListenerOnPostExecute(result);
        }
    
        private AsyncTaskListener<Result> mListener;
        public interface AsyncTaskListener<Result>{
            public void onPostExecute(Result result);
        }
        public void listenWith(AsyncTaskListener<Result> l){
            mListener = l;
        }
        private void notifyListenerOnPostExecute(Result result){
            if(mListener != null)
                mListener.onPostExecute(result);
        }
    
    }
    

    因此,首先扩展ListenableAsyncTask,而不是AsyncTask。然后在您的UI代码中,创建一个具体的实例并设置listenWith(…)。

        6
  •  2
  •   Sujal Mandal    11 年前

    这个问题已经得到了回答,我想我还在发布应该如何做。。

    主要活动类别

      public class MainActivity extends Activity implements OnClickListener
        {
    
            TextView Ctemp;
    
            @Override
            protected void onCreate(Bundle savedInstanceState)
            {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                Ctemp = (TextView) findViewById(R.id.Ctemp);
                doConv = (Button) findViewById(R.id.doConv);
                doConv.setOnClickListener(this);
            }
    
            @Override
            public void onClick(View arg0) // The conversion to do
            {
                new asyncConvert(this).execute();
            }
        }
    

    现在在async类中

    public class asyncConvert extends AsyncTask<Void, Void, String>
    {
        SoapPrimitive response = null;
        Context context;
    
        public asyncConvert(Context callerclass)
        {
            contextGUI = callerclass;
        }
    .
    .
    .
    .
    protected void onPostExecute(String result)
        {
            ((MainActivity) contextGUI).Ctemp.setText(result); // changing TextView
        }
    }
    
        7
  •  1
  •   Lucky Rana    11 年前
        /**
         * Background Async Task to Load all product by making HTTP Request
         * */
         public  static class updateTExtviewAsyncTask extends AsyncTask<String, String, String> {
    
            Context context;
            ProgressDialog pDialog;
            String id, name;
    
            String state_id;
    
            //--- Constructor for getting network id from asking method
    
            public  updateTExtviewAsyncTask(Context context,String id,String city) 
            {
                context   = context;
                state_id  = id;
                city_name = city;
            }       
            /* *
             * Before starting background thread Show Progress Dialog
             * */
            @Override
            protected void onPreExecute() 
            {
                super.onPreExecute();
                pDialog = ProgressDialog.show(context, "","Please wait...", true, true);
                pDialog.show();
    
            }
    
            /**
             * getting All products from url
             * */
            protected String doInBackground(String... args) 
            {
                return null;
            }
    
            /**
             * After completing background task Dismiss the progress dialog
             * **/
                protected void onPostExecute(String file_url)  {
    
                         YourClass.UpdateTextViewData("Textview data");
            }
        }
    

    //将此代码放入活动类中,并声明更新textview静态

        public static void  UpdateTextViewData(String tvData) 
    {
       tv.setText(tvData);
    }