ورود

View Full Version : نحوه برگرداندن مقدار از AsyncTasks به activity



keyhan.taktaz
یک شنبه 22 دی 1392, 03:22 صبح
سلام
من یک کلاس AsyncTasks دارم که از داخلActivity اجراش میکنم و یک مقدار POST رو به یک سرور میفرستم و جوابشو میگیرم.اما دیگه نمیتونم برگردونم به Activity مقدارش رو.
لطفا کمک کنید

rubiks.kde
یک شنبه 22 دی 1392, 10:10 صبح
شما میتونید مقدار رو برگردونید.مقدار بازگشتی رو به عنوان مقدار بازگشتی کلاس ست کنید اون وقت با اجرای doInBackground اون مقدار به تابع onPostExecute فرستاده میشه.
که از طریق تابع onPostExecute میتوانید به ui دسترسی داشته باشید.

private class DoBackgroundTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalBytesDownloaded = 0;

for (int i = 0; i < count; i++) {
totalBytesDownloaded += DownloadFile(urls[i]);
//---calculate percentage downloaded and
// report its progress---
publishProgress((int) (((i+1) / (float) count) * 100));
}

return totalBytesDownloaded;
}
protected void onProgressUpdate(Integer... progress) {

Log.d("Downloading files", String.valueOf(progress[0])
+ "% downloaded");

Toast.makeText(getBaseContext(), String.valueOf(progress[0])
+ "% downloaded", Toast.LENGTH_LONG).show();
}
protected void onPostExecute(Long result) {

Toast.makeText(getBaseContext(), "Downloaded " + result + " bytes",
Toast.LENGTH_LONG).show();
stopSelf();
}

keyhan.taktaz
یک شنبه 22 دی 1392, 13:04 عصر
میخوام از طریق onPostExecute مقدار رو برگردونم به activity ای که این کلاس از اونجا صدا شده تا اونجا پردازش بشه .

rubiks.kde
یک شنبه 22 دی 1392, 13:44 عصر
کلاس آسینک توی یک کلاس دیگه هست ؟؟؟

اگه این طوره به دو صورت میشه جواب داد:

1 - استفاده از تابع get () که صبر میکنه تا آسینک تموم بشه و اون خروجی رو برمیگردونه براتون.
String serverResponse = apiObj.execute(nameValuePairs).get();

2-روش دوم استفاده از listener مانند نمونه زیر :

import android.os.AsyncTask;

// Remember to change object type <> to what you need
public class TestTask extends AsyncTask<Object,Object,Object> {

public interface OnTaskCompleted{
void onTaskCompleted();
}

private OnTaskCompleted listener;

public TestTask(OnTaskCompleted listener){
this.listener = listener;
}

protected void onPostExecute(Object o){
// Call the interface method
if (listener != null)
listener.onTaskCompleted();
}

@Override
protected Object doInBackground(Object... params) {
// The sleep() is just to simulate activity and delay
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}

حال میتونید به این صورت داخل اکتیویتی استفاده کنید.

public class MainActivity extends Activity {

private boolean status = false;

private OnTaskCompleted listener = new OnTaskCompleted() {
public void onTaskCompleted() {
status = true;
Toast.makeText(MainActivity.this, "Status: " + status, Toast.LENGTH_SHORT).show();
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(MainActivity.this, "Status: " + status, Toast.LENGTH_SHORT).show();
new TestTask(listener).execute("Testing");
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}

keyhan.taktaz
یک شنبه 22 دی 1392, 14:00 عصر
کد دوم خیلی برام مبهم بود،چون اصلا مقدار برگشتی نمیبینم.
کد اول رو استفا ده کردم،فقط مشکل اینجاست که موقع استفاده ProgressDialog از کار می افته و برنامه تا وقتی که اطلاعات رو از سرور دریافت نکرده کرش می کنه.
تورو خدا منو کمک کنید،چند روزه اینجا گیر کردم.

rubiks.kde
یک شنبه 22 دی 1392, 14:48 عصر
کد کلاس آسینک تسک رو اینجا بزارید مقدار بازگشتیش هم مشخص باشه(کدهای داخل doInBackground نمیخواد) فقط طوری که مشخص باشه خروجی چیه.

keyhan.taktaz
یک شنبه 22 دی 1392, 16:55 عصر
ممنون از زحمات شما دوست عزیز ،امیدوارم اجرتون رو از خدا بگیرید.
این کلاس ورودی json میگیره و خروجی هم متغیر temp باید باشه.
نکته : در قسمت onPostExecute با دستورای که کامنتش کردم متغیر temp رو میشه به اکتیویتی برگردوند،اما مشکل اینجاست که این کلاس برای یک اکتیویتی خاص مورد استفاده قرار نمیگیره که اسم اکتیویتی رو بدونم و اینکارو بکنم.

package com.tsk;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;


import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;


import android.app.ProgressDialog;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;


public class Connection extends AsyncTask<JSONObject, Void, String>{
private static final String TAG = "Connection Class";
private String temp = null;
protected static String url;
private ProgressDialog dialog;
private Context context;
private boolean running = true;
public Connection(Context cxt,String router){
Log.i(TAG, "Connection Started");
this.refererName = refererName;
url = LinkManager.getUrl(router);
context = cxt;
dialog = new ProgressDialog(context);
boolean a = checkNetwork();
Log.i(TAG,"BOOL IS : " + a);
if(!checkNetwork())
{
running = false;
this.cancel(true);
}
}
public static String POST(JSONObject data){

InputStream inputStream = null;
String result = "";
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
String json = "";

json = data.toString();


StringEntity se = new StringEntity(json);

httpPost.setEntity(se);

httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");

HttpResponse httpResponse = httpclient.execute(httpPost);

inputStream = httpResponse.getEntity().getContent();

if(inputStream != null)
{
result = convertInputStreamToString(inputStream);
Log.v(TAG, result);
}
else
{
result = "Did not work!";
}

} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}

// 11. return result
return result;
}

private static String convertInputStreamToString(InputStream inputStream) throws IOException{
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
String line = "";
String result = "";
while((line = bufferedReader.readLine()) != null)
result += line;

inputStream.close();
return result;

}
@Override
protected void onPreExecute() {
// initialize the progress bar
// set maximum progress to 100.
Log.i(TAG, "Method Executed");
if(running)
{
dialog.setTitle("لطفا صبر کنید");
dialog.show();
}

}
@Override
protected void onCancelled() {
running = false;
}
@Override
protected String doInBackground(JSONObject... params) {
Log.i(TAG, url);
if(running) {
Log.i(TAG, "Background Method Started");
SystemClock.sleep(2000);
temp = POST(params[0]);
}
return temp;

}

@Override
protected void onPostExecute(String result) {
// async task finished
dialog.dismiss();
Log.i(TAG, "Method completed");
// Login login = (Login)context;
// login.checkSuccess(temp);

}
public String getResponse(){
return temp;
}
private boolean checkNetwork() {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERV ICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return true;
} else {
Toast.makeText(context,"Sorry, Network Unavailable! :(", Toast.LENGTH_LONG).show();
}
return false;
}

}

keyhan.taktaz
یک شنبه 22 دی 1392, 19:20 عصر
خوب دوستان.
با استفاده از روش زیر میتونیم یک مقدار رو از یک AsyncTask به کلاسی که AsyncTask رو توش فراخوانی کردیم برگردونیم:

ابتدا این کد رو به AsyncTask اضافه میکنیم :

private OnTaskCompleted listener;
public interface OnTaskCompleted{
void onTaskCompleted(String result);
}

public void setOnTaskCompleted(OnTaskCompleted listener){
this.listener = listener;
}

و همچنین کد زیر رو به onPostExecute اضافه میکنیم :

if(listener != null) listener.onTaskCompleted(result);

خوب حالا کد های زیر رو به کلاسی اضافه کنید که از داخلش AsyncTask و فراخوانی کردید(میتونه یک Activity باشه) :
توجه داشته باشید کد زیر رو باید بعد از اینکه object رو ساختید اضافه کنید (بعد از ساخت شی و قبل از اجرای execute)

connection.setOnTaskCompleted(listener);

و کد زیر رو هم به عنوان تابع در کلاس بنویسید :

public OnTaskCompleted listener = new OnTaskCompleted() {
@Override
public void onTaskCompleted(String result) {
// TODO Auto-generated method stub
Toast.makeText(Login.this,result ,Toast.LENGTH_LONG).show();
}


};

mohsen22
یک شنبه 22 دی 1392, 21:50 عصر
ممنون--- ممکنه مثال عملی رو بزارید ببینیم دقیقا چی کار می کنه ؟؟
مرسی