Android中的MVC架构:异步更新使用应用程序还是服务?

6

非常抱歉我的第一篇帖子没有表述清楚。

这是情况:我有一些需要从互联网上刷新的数据。我们称之为Model

我的需求:基本上听起来像是一个MVC模型,其中Model也被保留在本地(私有)存储中。 Model及其相关方法是应用程序级别的。 有几个Activity显示和操作它的不同方面:

  • 用户浏览显示Model的不同Activity。当前我为所有元素设置了一个ListActivity,以及一个用于一个元素详情的Activity
  • 有时需要刷新Model。当然,这是在不同线程上完成的。 刷新可以从几个Activity触发。
  • 有几个(耗时的)常见任务可以从不同的Activity触发
  • 我的应用程序在启动和停止时将Model加载和保存到私有存储中

我的问题:我不确定在哪里放置Model和相关任务。此外,我不知道要使用什么机制通知Activity。目前我想到了两种方法:

  • 使用Service并发送广播。将保存到磁盘的操作放在Service#onDestroyed()中,因此我希望将其绑定到Activity上以最小化它。 在这一点上,我也不确定如何传递更新的信息:是在Binder中提供一个getter,还是将其包含在广播消息中。
  • 自定义Application对象,以便全局可用刷新方法getter。然后我使用AsyncTaskActivity中执行更新。 如果有其他Activity落后于当前Activity,则当用户返回时,它们将在onResume()中更新。

我没有使用具有静态方法的类的原因:

  • 我需要将Model保存和存储到磁盘中。
  • 其中一些方法需要Context用于显示toast、通知、缓存等。

此外,我不会将这些功能放在Activity中,因为有几个活动可以操作相同的持久数据。

下面是说明我的伪代码:

使用Service:

/** Service maintaining state and performing background tasks */
class MyService extends Service {
    Model mModel;
    Binder mBinder;

    onCreate() {
        super.onCreate();
        mBinder = new Binder();
        // load mModel from disk, or do default initialization
    }

    onDestroy() {
        super.onDestroy();
        // save mModel to disk
    }

    onBind() {
        return mBinder;
    }

    class Binder {
        refresh() {
            new AsyncTask() {
                doInBackground() {
                    // update mModel from Internet
                }
                onPostExecute() {
                    sendBroadcasts(new Intent("my.package.REFRESHED"));
                }
            }.execute();
        }

        getState() {
            return mModel.getState();
        }
    }
}

/** Activity displaying result */
class MyActivity extends ListActivity {
    MyService.Binder mBinder;

    onCreate() {
        super.onCreate();
        // register mReceiver
        // bind service
    }

    onDestroy() {
        super.onDestroy();
        // unbind service
        // unregister mReceiver
    }

    /** Invokes time-consuming update */
    refresh() {
        // binding is asynchronous, and user may trigger refreshing too early
        if (mBinder != null) {
            mBinder.refresh();
        }
    }

    BroadcastReceiver mReceiver = new BroadcastReceiver() {
        onReceive(Intent intent) {
            if ("my.package.REFRESHED".equals(intent.getAction())
                    && mBinder != null) {
                updateViews(mBinder.getState());
            }
        }
    };
}

将功能在自定义应用程序对象中全局访问。
/** Custom Application providing domain specific functionalities */
class MyApplication extends Application {
    Model mModel;

    onCreate() {
        super.onCreate();
        // load mModel from disk, or do default initialization
    }

    onTerminate() {
        super.onTerminate();
        // save mModel to disk
    }

    void refresh() {
        /** time-consuming */
    }

    getState() {
        return mModel.getState();
    }
}

/** Activity displaying result */
class MyActivity extends ListActivity {
    onResume() {
        super.onResume();

        // in case some top Activities have refreshed
        // and user is navigating back
        updateViews(((MyApplication)getApplicationContext()).getState());
    }

    /** Invokes time-consuming update */
    refresh() {
        new AsyncTask() {
            doInBackground() {
                ((MyApplication)getApplicationContext()).refresh();
            }
            onPostExecute() {
                // update the ListView according to result
                updateViews(((MyApplication)getApplicationContext()).getState());
            }
        }.execute();
    }
}

我认为“服务”方法的弱点是复杂性,因为绑定是异步的。而且很可能由于我同时拥有“ListActivity”和“Activity”,需要重复一些代码。
对于“应用程序”方法,文档指出不要依赖于调用“onTerminate()”。
我知道我很笨拙。解决这种问题的常规方法是什么?
非常感谢。
3个回答

1

Service通常适用于不绑定单个Activity的内容(通常与NotificationManagerWidget一起使用)。但这似乎不是这种情况。
因此,我的建议是拥有一个经过良好设计的AsyncTask,通过SharedPreferences/SQLite自身来管理状态(而不是滥用Application),并将从ListActivity启动。


0

你可以扩展一个 BroadcastReceiver 而不是 Service,当它完成它需要做的事情时,它会加载一个带有结果的 Activity。


我的问题,没有表达清楚。我有几个活动(Activities),它们访问和改变同一应用程序数据的部分 :) - Phil

0
你没有解释你获取什么样的信息,但这行很重要:
这些任务涉及需要在应用程序启动和停止时优雅地加载和保存的状态。
如果是这种情况,为什么不在 Activity 内部执行 AsynTask?
我曾经和你有同样的担忧,即使用 Intent 传递 ArrayList,但我有一个应用程序确切地执行了这个功能,并且我没有性能问题。

非常抱歉我没有表达清楚。我没有将它放在一个Activity中,因为我有几个Activity访问和改变同一片应用程序数据。我已经编辑了我的帖子。 - Phil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接