2012-09-03 10 views
36

मुझे आंतरिक कक्षा से नफरत है।एंड्रॉइड: AsyncTask से एक यूआई को कैसे अपडेट करें यदि AsyncTask एक अलग वर्ग में है?

मेरे पास एक मुख्य गतिविधि है जिसने 'शॉर्ट-लाइफ' AsyncTask लॉन्च किया है।

AsyncTask एक अलग फाइल में है, मुख्य गतिविधि का एक आंतरिक वर्ग

मैं async कार्य मुख्य गतिविधि से एक TextView अद्यतन करता है की जरूरत नहीं है।

मैं मैं onProgressUpdate से एक TextView अद्यतन कर सकते हैं पता है, अगर AsyncTask एक बाहरी, स्वतंत्र, async कार्य से एक आंतरिक वर्ग

लेकिन यह कैसे है?

अद्यतन: यह काम कर दिखाई देता है:

acitivty में मैं काम फोन

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

निर्माता में मैं है

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

जहां डिबग AsyncTask के एक निजी क्षेत्र था।

तो onProgressUpdate मैं

debug.append(text); 

आप सुझाव

+0

आपका मतलब है कि किसी अन्य वर्ग में, आप यूआई तक पहुंचना चाहते हैं? –

+0

हां। मुझे AsyncTask से टेक्स्ट व्यू को अपडेट करने की आवश्यकता है। – realtebo

+0

आप अपने कन्स्ट्रक्टर में संदर्भ पास कर सकते हैं और इसे अपने गतिविधि क्लास पर कास्टिंग कर सकते हैं, तो आप runOnUIThread विधि का उपयोग करके टेक्स्ट व्यू बदल सकते हैं। –

उत्तर

31

संपादित मैं उपयोग करने के लिए WeakReference


AsyncTask हमेशा Activity से अलग वर्ग है जवाब संपादित, लेकिन मुझे लगता है तुम्हारा मतलब यह, अपनी गतिविधि वर्ग फ़ाइल की तुलना में अलग फाइल में है, इसलिए आप से लाभ नहीं कर सकते हैं गतिविधि की आंतरिक कक्षा होने के नाते। बस अपने Async कार्य करने के लिए तर्क के रूप में गतिविधि संदर्भ पारित (यानी अपने निर्माता के लिए)

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

ध्यान दें कि हमारे Activity चला गया हो सकता है, जबकि doInBackground() (ताकि refere के कार्य प्रगति पर है एनसी वापस null बन सकता है), लेकिन WeakReference का उपयोग करके हम जीसी को इसे इकट्ठा करने से रोकते हैं (और स्मृति को लीक करते हैं) और जैसे ही गतिविधि समाप्त हो जाती है, आमतौर पर यह स्थिति को अपडेट करने का प्रयास करने के लिए व्यर्थ है (फिर भी, आपके तर्क के आधार पर आप चाहें आंतरिक स्थिति बदलने या डीबी अपडेट करने जैसे कुछ करने के लिए, लेकिन यूआई को छूना छोड़ दिया जाना चाहिए)।

+2

यदि आप इस मार्ग पर जाते हैं, तो गतिविधि गतिविधि को केवल गतिविधि के बजाय वीक रेफरेंस के रूप में पकड़ना बेहतर होता है। IMO। – newbyca

+0

"वीक रेफरेंस" क्या है? – realtebo

+0

वेबनेटमोबाइल।कॉम, आह ठीक है, मुझे यकीन नहीं था, जानना अच्छा है। @realtebo, http://developer.android.com/reference/java/lang/ref/WeakReference.html – newbyca

3

के सभी के लिए धन्यवाद बस संदर्भ (गतिविधि या जो कुछ भी) अपने AsyncTask के एक निर्माता में और onSuccess या onProgressUpdate कॉल जो कुछ भी आप की जरूरत है तो में पारित कर सकते हैं संदर्भ पर।

2

अपने टेक्स्ट क्लास को अपडेट करने के लिए अपने गतिविधि वर्ग में संदर्भ में एक स्थिर कार्य करें और फिर इस फ़ंक्शन को अपने AsynkTask क्लास में अपडेट करने के लिए कॉल करें।

गतिविधि वर्ग में: public static void updateTextView() {

// यहाँ अपने कोड}

AynckTask वर्ग कॉल इस समारोह में।

+0

सही। धन्यवाद! – hoss

3

मैंने इस तरह के परिदृश्य के लिए AsyncTask में एक छोटा सा विस्तार लिखा था। यह आपको एक अलग वर्ग में अपने AsyncTask रखने के लिए अनुमति देता है, लेकिन यह भी आप कार्य के पूरा होने के लिए सुविधाजनक पहुँच देता है:

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 का विस्तार। फिर अपने यूआई कोड में, एक ठोस उदाहरण बनाएं और सुनें (...)।

2

प्रश्न पहले से ही उत्तर दिया गया है, अभी भी im पोस्टिंग यह कैसे किया जाना चाहिए मैं लगता है ..

MainActivity वर्ग

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 
    } 
} 
1
/** 
    * 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); 
} 
18

इंटरफ़ेस 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 द्वारा दिया() के रूप में "परिणाम" मिल जाएगा {वापसी "।";}

जबकि "dataSendToActivity.sendData (परिणाम);" यह गतिविधि की ओवरराइड विधि को कॉल करेगा "सार्वजनिक शून्य प्रेषण (स्ट्रिंग स्ट्र) {}"।

एक बढ़त मामले का ध्यान रखें: this पारित करने के लिए सुनिश्चित करें, यानी आप AsyncTask को वर्तमान गतिविधि के संदर्भ और नहीं अपनी गतिविधि का एक और उदाहरण बनाने के लिए, अन्यथा अपने Activity नष्ट हो जाएगा और नए बन जाता है।

+0

यह पहली झलक पर सही हो सकता है, एक गतिविधि में एकाधिक सामान्य 'AsyncTask' को संभाल नहीं सकता है। – zionpi

+0

यह एक अच्छा समाधान है। एक इंटरफ़ेस को कार्यान्वित करना युग्मन को ढीला करता है और इस एंड्रॉइड डेवलपर वीडियो में अनुशंसा की जाती है - https://www.youtube.com/watch?v=jtlRNNhane0&index=4&list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE। –

संबंधित मुद्दे