Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java AsyncTask的最佳实践:通用参数与多参数?_Java_Android_Generics_Android Asynctask - Fatal编程技术网

Java AsyncTask的最佳实践:通用参数与多参数?

Java AsyncTask的最佳实践:通用参数与多参数?,java,android,generics,android-asynctask,Java,Android,Generics,Android Asynctask,如果一个AsyncTask需要返回一个结果,那么通常会为回调创建一个接口,并通过构造函数传递类(实现该接口) 另外,如果AsyncTask(或任何其他非活动类)需要访问ApplicationContext,则构造函数中的上下文参数可以解决此问题 但是,如果我同时需要它们,并且我的调用者一方面是一个活动(因此也是我的上下文),另一方面也是我的实现接口,该怎么办 AsyncTask的构造函数应该看起来像Constructor1还是Constructor2?这里的最佳实践是什么?为什么 (如果正确答案

如果一个
AsyncTask
需要返回一个结果,那么通常会为回调创建一个接口,并通过构造函数传递类(实现该接口)

另外,如果
AsyncTask
(或任何其他非活动类)需要访问
ApplicationContext
,则构造函数中的
上下文
参数可以解决此问题

但是,如果我同时需要它们,并且我的调用者一方面是一个
活动
(因此也是我的
上下文
),另一方面也是我的实现接口,该怎么办

AsyncTask
的构造函数应该看起来像
Constructor1
还是
Constructor2
?这里的最佳实践是什么?为什么

(如果正确答案是
Constructor2
:我是否应该将变量合并到一个通用类型
T
?)

公共类MyTask扩展了AsyncTask{
回调;
Context;//更新:此处应使用WeakReference以避免内存泄漏!
//构造器1
MyTask(回调、上下文){
this.callback=回调;
this.context=上下文;
}
//建造师2
MyTask(T contextAndCallback){
this.callback=contextAndCallback;
this.context=contextAndCallback;
}
@凌驾
受保护的Void doInBackground(Void…参数){
//做需要上下文的事情
返回null;
}
@凌驾
受保护的void onPostExecute(void避免){
super.onPostExecute(避免);
callback.callbackMethod();
}
接口回调{
void callbackMethod();
}
}
致以最良好的祝愿, 温克勒

更新28.04 将AsyncTask作为匿名类实现

在我的
活动
中将
异步任务
实现为一个匿名类将是一个可能的解决方案-是的

但是在我的例子中,我需要在不同的地方执行
AsyncTask
,所以我不得不多次实现它,这对我来说不是一个好的解决方案

只有这些选项吗?


我不知道我的问题是否还有其他解决办法。我刚想到那两个。如果有更好的解决方案(“最佳实践”),请告诉我

这取决于您要归档的内容

  • 使用双参数构造函数,您可以灵活地使用任何活动、服务或任何地方的上下文,并在另一个对象(例如扩展的TextView)内实现回调,还可以通过 例如,实现回调接口。这使您可以对代码执行更多有用的操作,并在任何需要的地方接收回调事件

  • 使用合并参数的方式,您将失去这种灵活性,但您可以确保绑定到此AsyncTask的对象具有上下文并实现回调。换句话说,必须将上下文和回调放在一起。如果您需要强制自己和其他开发人员在这些条件下使用此异步任务,那么这将非常有用。当然,有一种“黑客”方式,例如实现一个伪对象并从另一个方面获取上下文,但这将导致代码中隐藏的依赖项,以及大量的实现,这将导致代码不清楚,并且“非优雅”解决方案

从架构的角度来看,最好的方法,或者无论他们在大学里向我们展示了什么,就是永远不要合并参数和返回,以使您的代码从其他方面更加可重用,并避免隐藏的依赖关系。此外,您还可以尝试另一种方法,如使用服务或队列


请记住,上下文可以是GC,AcsiCt任务可以继续运行。

您确定这些选项是唯一的吗?您是否已经探索了Builder模式?考虑用队列替换回调吗?在中定义,您不必为了获得所需内容而干扰构造函数。在
doInBackground
中访问上下文是导致内存泄漏的一种方法。我会使用WeakReference来代替它。@OldCurmudgeon我更新了问题,因此将
上下文
传递给
异步任务
是一种不好的做法。还有什么替代方法吗?如表示使用包含未被GC“监视”的poiner的WeakReference。然后,当您要在AsyncTask中使用上下文时,请检查是否仍处于活动状态
public class MyTask<T extends Context & Callback> extends AsyncTask<Void, Void, Void> {

    Callback callback;
    Context context; // Update: WeakReference<Context> should be used here to avoid memory leaks!

    // Constructor 1
    MyTask(Callback callback, Context context) {
        this.callback = callback;
        this.context = context;
    }

    // Constructor 2
    MyTask(T contextAndCallback) {
        this.callback = contextAndCallback;
        this.context = contextAndCallback;
    }

    @Override
    protected Void doInBackground(Void... params) {
        // do stuff for which the context is needed for
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        callback.callbackMethod();
    }

    interface Callback {
        void callbackMethod();
    }
}