如何进行活动以显示从服务获得的数据?

时间:2018-07-01 09:53:17

标签: java android kotlin android-livedata android-mvvm

我需要编写一个服务,该服务每30秒更新一次MainActivity中的列表。我将MVVM与ViewModel和LiveData一起使用,因此我的Service类如下:

public class ArticleJobService extends JobService {

    public static String TAG = "ArticleJobService";

    private Context context = this;

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        Log.d(TAG, "onStartJob");
        MainActivity.PAGE_NUMBER++;
        LiveData<List<Article>> liveArticles = ArticleRepository.getInstance(getApplication()).getArticles(MainActivity.PAGE_NUMBER);

        liveArticles.observeForever(new Observer<List<Article>>() {
            @Override
            public void onChanged(@Nullable List<Article> articles) {
                Log.d(TAG, "onStartJob - onChanged!!!!!!");
                liveArticles.removeObserver(this);
                NotificationUtils.showNotification(context, articles.get(0).getSectionName(), articles.get(0).getWebTitle());
                jobFinished(jobParameters, true);
            }
        });
        return true;
    }
}

通知类别:

public static void showNotification(Context context, String section, String title) {
    PendingIntent contentPendingIntent = PendingIntent.getActivity
            (context, REQUEST_CODE, new Intent(context, MainActivity.class),
                    PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationManager manager =
            (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        manager.createNotificationChannel(createNotificationChannel(context));
    }

    NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
            .setContentTitle(section)
            .setContentText(title)
            .setContentIntent(contentPendingIntent)
            .setSmallIcon(R.drawable.app_icon)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setAutoCancel(true);

    manager.notify(0, builder.build());

}

当JobService中的Onchanged工作时,我会得到列表并显示通知。通知打开MainActivity,它会像往常一样对api进行新的调用。为了使MainActivity显示从服务中获得的列表,我必须进行哪些更改???我真的不能把它们绑在一起。 我听说过IPC,但不会这样做,我想要一些更简单的实践,但我肯定确实不知道。 另外,有两种情况:通知到来且MainActivity已打开,应用程序已打开但MainActivity不在前台,而应用程序在后台或关闭。我应该如何处理这些情况?

另请参阅MainActivity onCreate中的一段代码:

 mArticleViewModel = ViewModelProviders.of(this).get(ArticleViewModel.class);
    mArticleViewModel.getArticleList(PAGE_NUMBER).observe(this, articles -> {
        Log.d(TAG, "List<Result> onChanged!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        mProgressBar.setVisibility(View.GONE);
        mProgressBarMain.setVisibility(View.GONE);
        mIsLoading = false;
        mArticles = articles;

请提供此任务的最佳实践,我知道这是很常见的事情,因为我只是第一次这样做,而使用LiveData会使情况变得更加复杂。

这也是存储库代码:

public static ArticleRepository getInstance(Application application){
        if(INSTANCE == null){
            return  new ArticleRepository(application);
        }

        return INSTANCE;
    }

    private ArticleRepository(Application application) {
        Log.d(TAG, "ArticleRepository constructor");
        mContext = application;
        mArticles = new MutableLiveData<>();
        ArticleRoomDatabase db = ArticleRoomDatabase.getInstance(application);
        mArticleDao = db.articleDao();
    }

    public LiveData<List<Article>> getArticles(int page) {
        Log.d(TAG, "getArticles");
        if (NetworkUtils.isOnline(mContext)) {
            Log.d(TAG, "isOnline");
            mArticles = loadFromNetwork(page);
        } else {
            Log.d(TAG, "is NOT Online");
            mArticles = loadFromDB(page);
        }
    }

1 个答案:

答案 0 :(得分:1)

您具体有此问题,因为您的存储库实现不正确。

public LiveData<List<Article>> getArticles(int page) {
    Log.d(TAG, "getArticles");
    if (NetworkUtils.isOnline(mContext)) {
        Log.d(TAG, "isOnline");
        mArticles = loadFromNetwork(page);
    } else {
        Log.d(TAG, "is NOT Online");
        mArticles = loadFromDB(page);
    }
}

如果您检查NetworkBoundResource的代码,则诀窍是您拥有一个LiveData,该LiveData将从网络加载和从数据库加载的功能绑定在一起。

对于您来说,只要有网络访问权限,您就将替换数据库的自动更新查询结果-这就是为什么您无法更新MainActivity的原因。

最简单的方法(不使用MediatorLiveData)是在存储库上具有两个独立的功能:一个用于fetchFromNetwork,另一个用于fetchFromDatabase。 MainActivity应该始终从数据库中获取数据,而Service总是从网络中触发负载(并通过Dao将其直接插入数据库中)。

这样,当Service将数据插入后台线程中的DB中时,MainActivity中的observe函数将接收最新数据。