我正在开发一个应用程序,其中在我需要通过Http检索数据的许多活动中。 一旦我有数据,我在onPostExecute()回调方法中处理它。Android异步任务重用
这很好,如果我将async任务定义为内联类,但是因为我想在一些活动中做同样的处理,所以我将它定义为外部类。
所以问题是,使用外部类如何将“事件”返回给调用类作为传递数据的手段。我知道如何在C#中做到这一点,但我是Java新手,无法看到如何实现这一点。
我正在开发一个应用程序,其中在我需要通过Http检索数据的许多活动中。 一旦我有数据,我在onPostExecute()回调方法中处理它。Android异步任务重用
这很好,如果我将async任务定义为内联类,但是因为我想在一些活动中做同样的处理,所以我将它定义为外部类。
所以问题是,使用外部类如何将“事件”返回给调用类作为传递数据的手段。我知道如何在C#中做到这一点,但我是Java新手,无法看到如何实现这一点。
虽然听众在技术上是正确的,但我会声称它太复杂或不够复杂。
这里有一个简单的解决方案:
class Foo {
class Bar extends AsyncTask<Void, Void, Result> {
public void onPostExecute(Result res) {
doSomething(res);
}
}
public void doSomething(Result res) {
/// process result
}
public void startTask() {
new Bar().execute();
}
}
等同于:
class Bar extends AsyncTask<Void, Void, Result> {
private final Foo foo;
public Bar(Foo foo) { this.foo = foo; }
public void onPostExecute(Result res) {
foo.doSomething(res);
}
}
class Foo {
public void doSomething(Result res) {
/// process result
}
public void startTask() {
new Bar(this).execute();
}
}
...是你问这是什么:当你拉内部类了,你失去了隐式指针。只需将其明确并通过即可。
坏消息是存在各种由此解决方案引起的内存泄漏和生命周期问题。我会非常多建议,在您的程序变得更大之前,您正在考虑使用IntentService而不是AsyncTask,并使用Handler或Activity.runOnUiThread将结果返回到UI线程。
一种方法:
定义名为ParentActivity
父抽象类(延伸当然活性)。是否包含抽象方法onAsyncCallback();
让每个使用该任务的类都扩展该类并实现该方法。
在您的AsyncTask构造函数中,让它接受ParentActivity
。
如
ParentActivity activity;
public MyTask (ParentActivity myActivity)
{
this.activity = myActivity;
}
当onPostExecute()
做,根本就
activity.onAsyncCallback(data);
这也与接口工作,它做同样的事情,除了这一翻译你的构造在听者接受实例。
尝试制作自己的http请求类,以扩展AsyncTask并将其放在“doInBackground”调用中。你的方式你只需要使用url和params来实例化你的类并阅读响应。这对我有效。
这里是例子:
public class HttpRequest extends AsyncTask<String, Void, String> {
public String url;
public List<NameValuePair> nameValuePairs;
public String httpResponse =null;
public HttpRequest(String _url, List<NameValuePair> _nameValuePairs) {
url = _url;
nameValuePairs=_nameValuePairs;
}
@Override
protected String doInBackground(String... params) {
httpResponse = getWebPageWithFormData(url, nameValuePairs);
return "";
}
public static String getWebPageWithFormData(String url, List<NameValuePair> nameValuePairs){
String html = "";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
if (nameValuePairs!=null){
try {httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));}
catch (Exception e){}
}
HttpResponse response = null;
try {
response = httpclient.execute(httppost);
}
catch (ClientProtocolException e) { return ""; }
catch (IOException e) { return ""; }
int responseCode = response.getStatusLine().getStatusCode();
switch(responseCode) {
case 200:
HttpEntity entity = response.getEntity();
if(entity != null) {
try{ html = EntityUtils.toString(entity);}
catch (Exception e) {}
}
break;
}
return html;
}
}
如果你想要做一个干净的方式尝试以下方法
首先创建一个包含所有的异步调用的名称枚举
public enum TaskType {
USER_LOGIN(1), GET_PRODUCTS(2), GET_EMPLOYEE(3);
int value;
private TaskType(int value) {
this.value = value;
}
}
然后创建一个界面
public interface AsyncTaskListener {
public void onTaskCompleted(String result, TaskType taskType);
}
现在实施的活动这个界面,你要叫GetAsyncTask 如: -
public class LoginActivity extends Activity implements AsyncTaskListener {
protected void onCreate(Bundle savedInstanceState) {
String url = ".....";
new GetAsyncTask(LoginActivity.this, LoginActivity.this, TaskType.USER_LOGIN).execute(url);
}
...
public void onTaskCompleted(String result, TaskType taskType) {
if(taskType == TaskType.USER_LOGIN){
//your login result handling here
}
}
最后,这是你的AsyncTask
public class GetAsyncTask extends AsyncTask<String, Void, String> {
String outputStr;
ProgressDialog dialog;
Context context;
AsyncTaskListener taskListener;
TaskType taskType;
public GetAsyncTask(Context context, AsyncTaskListener taskListener, TaskType taskType){
this.context = context;
this.taskListener = taskListener;
this.taskType = taskType;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
}
@Override
protected String doInBackground(String... params) {
String urlString = params[0];
try {
URL url = new URL(urlString);
HttpURLConnection conn
= (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
if (conn.getResponseCode() != 200) {
throw new IOException(conn.getResponseMessage());
}
// Buffer the result into a string
BufferedReader rd = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
String jsonStr = sb.toString();
outputStr = jsonStr;
} catch (SocketTimeoutException e) {
outputStr = "timeout";
}catch(Exception e){
e.printStackTrace();
outputStr = "error";
}
return outputStr;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
taskListener.onTaskCompleted(result, taskType);
dialog.dismiss();
}
}
它可能会出现什么样的内存泄漏问题?你可以给一些关于如何使用IntentService而不是AysncTask的参考吗?我读了这个http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception,强烈建议在http请求中使用'AsyncTask()'。 – Stallman
我强烈反对6343166. AsyncTask问题的描述需要超过600个字符。只是谷歌为“AsyncTask内存泄漏”找到几十篇文章。有关如何使用IntentService的示例,请从eclipse/ADT中选择New> Other,然后在对话框中选择Android> Android Object> Next,然后选择Service(Intent Service)。你会得到一个很好的原型 –
http://stackoverflow.com/questions/25345087/intentservice-connected-to-server-listening建议不要使用'intent service' – Stallman