我正在开发一个应用程序,在许多活动中我需要通过 Http 检索数据。一旦我有了数据,我就会在 onPostExecute() 回调方法中处理它。
如果我将异步任务定义为内联类,这可以正常工作,但由于我想在许多活动中进行相同的处理,我将其定义为外部类。
所以问题是,使用外部类如何将“事件”发回给调用类,作为将数据传回的一种方式。我知道如何在 C# 中做到这一点,但我是 Java 新手,看不到如何实现这一点。
我正在开发一个应用程序,在许多活动中我需要通过 Http 检索数据。一旦我有了数据,我就会在 onPostExecute() 回调方法中处理它。
如果我将异步任务定义为内联类,这可以正常工作,但由于我想在许多活动中进行相同的处理,我将其定义为外部类。
所以问题是,使用外部类如何将“事件”发回给调用类,作为将数据传回的一种方式。我知道如何在 C# 中做到这一点,但我是 Java 新手,看不到如何实现这一点。
虽然 Listener 在技术上是正确的,但我认为它要么太复杂,要么不够复杂。
这是一个更简单的解决方案:
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
(当然是扩展Activity)。让它包含一个名为的抽象方法onAsyncCallback();
让每个使用该任务的类扩展该类并实现该方法。
在您的 AsyncTask 构造函数中,让它接受ParentActivity
.
例如
ParentActivity activity;
public MyTask (ParentActivity myActivity)
{
this.activity = myActivity;
}
完成后onPostExecute()
,只需执行
activity.onAsyncCallback(data);
这也适用于接口,它做同样的事情,除了你让构造函数在侦听器实例中接受。
如果您想以干净的方式进行操作,请尝试以下方法
首先创建一个包含所有异步调用名称的枚举
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();
}
}
使用侦听器模式。看看这里TaskListener,使用这个监听器的任务和调用任务的片段
尝试制作您自己的扩展 AsyncTask 的 http 请求类,然后将您的代码放在“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;
}
}