【问题标题】:Is passing interface to AsyncTask a good practice将接口传递给 AsyncTask 是一种好习惯
【发布时间】:2011-11-07 07:55:30
【问题描述】:

我有一个接口类

public interface AsyncTaskExecuteCommand {
public Object executeCommand(String jsonLocation) throws IOException,JSONException;
}

我有一个 HashMap 来存储这个接口的实例

public static HashMap<String,AsyncTaskExecuteCommand> executeCommandHashMap

executeCommandHashMap.put(COMMAND_CORE_FIELD_FETCH, new AsyncTaskExecuteCommand() {
        @Override
        public Object executeCommand(String jsonLocation) throws IOException, JSONException{
                           //return some thing
        }
    });

executeCommandHashMap.put(COMMAND_REGISTER_FIELD_FETCH, new AsyncTaskExecuteCommand() {
        @Override
        public Object executeCommand(String jsonLocation) throws IOException,
                JSONException {
                          //return some thing
        }
    });

我的 AsyncTask 名为 GeneralAsyncTask 包括

doInBackground(){

 AsyncTaskExecuteCommand asyncTaskExecuteCommand = executeCommandHashMap.get(params[0]);
 return asyncTaskExecuteCommand.executeCommand(params[1]);
}

而这个AsyncTask被称为

new GeneralAsyncTask().execute(COMMAND_REGISTER_FIELD_FETCH,"http://something");

我这样做是因为我的 AsyncTask 的一般结构保持不变,即它执行一些方法并返回一些值。只有方法执行类型和返回值会不同。如果我不实现将接口传递给 async任务,我最终创建了很多 AsyncTask 类。 那么,这种方法是解决我的方案的好方法吗?

【问题讨论】:

    标签: android interface android-asynctask


    【解决方案1】:

    看起来很复杂。您是否有理由不使用匿名类:

    new AsyncTask<String, Void, Object>() {
        @Override
        protected Object doInBackground(String... url) {
            //return some thing
        }
        protected void onPostExecute(Object result) {
            // do something with result
        }
    }.execute("http://something");
    

    【讨论】:

    • 我从没想过要像@Mister Smith 所说的那样设置一个匿名类。我会试一试并告诉我,如果它适用于我的情况
    • 这取决于你想做什么。如果你真的想要一个命令模式,以便你可以将函数作为对象传递,那么按照你和@Mister Smith 的建议去做是好的。但是,如果你只是想在后台运行一些东西,匿名 AsyncTask 会更好。
    【解决方案2】:

    如果您要对实现进行编码并将它们作为单独的类放在某个包中,则该接口是有意义的。这提高了可读性。如果目的不是每次都编写 AsynkTask,因为它有一些共同的部分,但只有 doInBackground 发生变化,那么我会将 AsyncTask 扩展为一个具体的泛型类,接受像这样的 GENERIC 接口:

        public interface MyTask<T,R> {
            R doInBackground(T... param);
        }
    

    类会是这样的(未测试):

        public class MyAsyncTask<T, P, R> extends AsyncTask<T, P, R> {
            private MyTask<T,R> task;
    
            public MyAsyncTask(MyTask<T,R> todo){
                task = todo;
            }
    
            protected R doInBackground(T... params) {
                if(task != null){
                    return task.doInBackground(params);
                } else {
                    return null;
                }
            }
    
            //Other AsyncTask mandatory methods implemented here. 
    
        }
    

    或者如果没有泛型也可以,那么接口和 AsyncTask 子类都是非泛型的。无论哪种方式,我都会对任务类和命令实现进行编码,将它们放在一个包中,使它们成为单例(或在某些主类中具有公共引用)并摆脱地图。

    【讨论】:

    • 无论哪种方式,我都会对任务类和命令实现进行编码,将它们放在一个包中,使它们成为单例(或在某些主类中有公共引用)并摆脱地图。 我已经为 AsyncTask 和 Interface 创建了单独的类。因此,不是放在地图上,而是说我应该有一个带有公共静态访问修饰符的类,由像//some class public static MyTask COMMAND_EXECUTE = new MyTask(){//some action} 这样的接口对象组成。如果可能的话,你能否给出一些关于如何实现它的代码提示
    • 我同意;如果您想将函数作为对象传递,那么按照您的建议做就可以了。
    • @laaptu 实例化对象的方式取决于您的需要。例如,如果您要在代码中多次使用给定命令,那么每次创建一个新实例有点浪费。在这些情况下,当类没有状态但主要是封装的过程时,我会将公共引用放在与地图相同的位置,或者在每个命令类(单例模式)中,或者更好的是,拥有自己的AsyncTaskExectuteCommandFactory 某处(工厂模式)。
    • @Mister Smith:虽然我没有使用过工厂模式,但我一定会学习并实施它,感谢您的指导
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多