android - मुख्य गतिविधि में OnPostExecute() का नतीजा कैसे प्राप्त करें क्योंकि AsyncTask एक अलग वर्ग है?




android-asynctask (10)

मेरे पास ये दो वर्ग हैं। मेरी मुख्य गतिविधि और एक जो AsyncTask विस्तारित करता है, अब मेरी मुख्य गतिविधि में मुझे OnPostExecute() में OnPostExecute() से परिणाम प्राप्त करने की आवश्यकता है। मैं अपनी मुख्य गतिविधि को परिणाम कैसे पास कर सकता हूं या प्राप्त कर सकता हूं?

नमूना कोड यहां दिए गए हैं।

मेरी मुख्य गतिविधि

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

}

यह 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);

}       

}   

अपनी गतिविधि कक्षा में एक स्थिर सदस्य बनाएँ। फिर onPostExecute दौरान मान असाइन करें

उदाहरण के लिए, यदि आपके AsyncTask का परिणाम स्ट्रिंग है, तो अपनी गतिविधि में एक सार्वजनिक स्थिर स्ट्रिंग बनाएं

public static String dataFromAsyncTask;

फिर, onPostExecute के onPostExecute में, बस अपनी मुख्य कक्षा में एक स्थिर कॉल करें और मान सेट करें।

MainActivity.dataFromAsyncTask = "result blah";


आप AsyncTask (या अधिभारित get(long, TimeUnit) की get() विधि को कॉल कर सकते हैं। यह विधि अवरुद्ध हो जाएगी जब तक AsyncTask ने अपना काम पूरा नहीं कर लिया है, उस बिंदु पर यह आपको Result

अपने एसिंक कार्य के निर्माण / आरंभ और get विधि को कॉल करने के बीच अन्य काम करना बुद्धिमान होगा, अन्यथा आप एसिंक कार्य को बहुत कुशलता से उपयोग नहीं कर रहे हैं।


आप इस कोड को अपने मुख्य वर्ग में आजमा सकते हैं। यह मेरे लिए काम करता है, लेकिन मैंने अन्य तरीकों से तरीकों को लागू किया है

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

आप इसे कुछ लाइनों में कर सकते हैं, जब आप अपने AsyncTask को कॉल करते हैं तो बस PostExecute पर ओवरराइड करें। यहां आपके लिए एक उदाहरण दिया गया है:

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

मुझे आशा है कि यह आपकी मदद करेगा, खुश कोडिंग :)


आसान:

  1. interface क्लास बनाएं, जहां String output वैकल्पिक है, या जो भी चर आप वापस करना चाहते हैं हो सकता है।

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. अपने AsyncTask क्लास पर जाएं, और फ़ील्ड के रूप में इंटरफ़ेस AsyncResponse घोषित करें:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. आपकी मुख्य गतिविधि में आपको इंटरफ़ेस AsyncResponse implements करने की आवश्यकता है।

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

अद्यतन करें

मुझे नहीं पता था कि यह आपके लिए बहुत पसंदीदा है। तो interface का उपयोग करने के लिए यहां सरल और सुविधाजनक तरीका है।

अभी भी एक ही interface का उपयोग कर। AsyncTask , आप इसे 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);
    }
}

इसे अपनी 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();

 }

या फिर गतिविधि पर इंटरफ़ेस को कार्यान्वित करना

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

जैसा कि आप उपर्युक्त 2 समाधान देख सकते हैं, पहले और तीसरे, इसे विधि processFinish बनाने की आवश्यकता है, दूसरा, विधि कॉलर पैरामीटर के अंदर है। तीसरा अधिक साफ है क्योंकि कोई नेस्टेड अज्ञात वर्ग नहीं है। उम्मीद है की यह मदद करेगा

युक्ति : अलग-अलग ऑब्जेक्ट्स प्राप्त करने के लिए String output , String response , और String result को विभिन्न मिलान प्रकारों में बदलें।


इंटरफेस का उपयोग करना आवश्यक नहीं है, क्योंकि आप इसके रिटर्न वैल्यू को बाहर नहीं प्राप्त कर सकते हैं और इसे किसी भी चर के लिए असाइन कर सकते हैं। आपको केवल get () विधि get () , जो प्रतीक्षा करता है जबकि doInBackground () अपने काम को समाप्त करता है, onPostExecute () परिणाम onPostExecute () , और इसे वापस करें:

String result = new myAsyncTask ().execute ().get ();

अब आप result वैरिएबल का उपयोग कर सकते हैं जहां आप चाहते हैं। यह मान डेटा प्रकार समान है जो onPostExecute () पर है। लेकिन आप इसे AsyncTask में AsyncTask में उपयोग नहीं कर सकते हैं, क्योंकि आपको एक infinty लूप मिलेगा। लेकिन मैं उन स्थितियों को नहीं सोच सकता जब आपको एक AsyncTask में AsyncTask का उपयोग करने की आवश्यकता होगी: /


मुझे लगा कि नीचे का दृष्टिकोण बहुत आसान है।

मैंने कॉलबैक के लिए एक इंटरफेस घोषित किया है

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

फिर सभी प्रकार के समांतर अनुरोधों का जवाब देने के लिए एसिंक्रोनस टास्क बनाया

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

}

फिर गतिविधि कक्षा में बटन क्लिक करते समय एसिंक्रोनस कार्य को बुलाया।

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


            }
        });

    }



}

धन्यवाद


मैं इसे थ्रेडिंग और हैंडलर / संदेश का उपयोग करके काम करता हूं। अनुसरण करने के चरण: एक प्रगति संवाद घोषित करें

ProgressDialog loadingdialog;

ऑपरेशन समाप्त होने पर संवाद बंद करने के लिए एक फ़ंक्शन बनाएं।

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

    }
    };

अपने निष्पादन विवरण कोड करें:

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

लोग इसे इतना कठिन क्यों बनाते हैं।

यह पर्याप्त होना चाहिए।

Async कार्य पर onPostExecute को लागू न करें, बल्कि इसे गतिविधि पर लागू करें:

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

}


}

हाय आप इस तरह कुछ कर सकते हैं:

  1. 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. मुख्य गतिविधि में जोड़ें

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