简体   繁体   English

在RecyclerView和服务中使用CountDownTimer

[英]Using CountDownTimer in a RecyclerView and a Service

I need to implement different CountDownTimers in a recyclerView. 我需要在recyclerView中实现不同的CountDownTimers。 I've put a BroadcastService class which contains my CountDownTimer. 我放了一个包含我的CountDownTimer的BroadcastService类。 It broadcasts to my MainActivity, where I'm updating the UI with a timer. 它广播到我的MainActivity,在那里我使用计时器更新UI。 However, I need to do this for several different timers with variable initial times. 但是,我需要为几个具有可变初始时间的不同计时器执行此操作。 When any of these timers hits zero, some unique code needs to be triggered. 当这些计时器中的任何一个达到零时,都需要触发一些唯一的代码。

Here's an example of how my BroadcastService class: 这是我的BroadcastService类的示例:

package com.example.cdt;

import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.util.Log;

public class BroadcastService extends Service {

    private final static String TAG = "BroadcastService";

    public static final String COUNTDOWN_BR = "your_package_name.countdown_br";
    Intent bi = new Intent(COUNTDOWN_BR);

    CountDownTimer cdt = null;

    @Override
        public void onCreate() {       
            super.onCreate();

            Log.i(TAG, "Starting timer...");

            cdt = new CountDownTimer(30000, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {

                    Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
                    bi.putExtra("countdown", millisUntilFinished);
                    sendBroadcast(bi);
                }

                @Override
                public void onFinish() {
                    Log.i(TAG, "Timer finished");
                }
            };

            cdt.start();
        }

        @Override
        public void onDestroy() {

            cdt.cancel();
            Log.i(TAG, "Timer cancelled");
            super.onDestroy();
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {       
            return super.onStartCommand(intent, flags, startId);
        }

        @Override
        public IBinder onBind(Intent arg0) {       
            return null;
        }
}

My MainActivity then receives the BroadCast Service's timer as such: 然后,我的MainActivity会收到BroadCast服务的计时器,如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    startService(new Intent(this, BroadcastService.class));
    Log.i(TAG, "Started service");
}

private BroadcastReceiver br = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {            
        updateGUI(intent); // or whatever method used to update your GUI fields
    }
};

@Override  
public void onResume() {
    super.onResume();        
    registerReceiver(br, new IntentFilter(BroadcastService.COUNTDOWN_BR));
    Log.i(TAG, "Registered broacast receiver");
    }

@Override
public void onPause() {
    super.onPause();
    unregisterReceiver(br);
    Log.i(TAG, "Unregistered broacast receiver");
}

@Override
public void onStop() {
    try {
        unregisterReceiver(br);
    } catch (Exception e) {
        // Receiver was probably already stopped in onPause()
    }
    super.onStop();
}
@Override
public void onDestroy() {        
    stopService(new Intent(this, BroadcastService.class));
    Log.i(TAG, "Stopped service");
    super.onDestroy();
}

private void updateGUI(Intent intent) {
    if (intent.getExtras() != null) {
        long millisUntilFinished = intent.getLongExtra("countdown", 0);
        Log.i(TAG, "Countdown seconds remaining: " +  millisUntilFinished / 1000);            
    }
}

Note that this code comes from How to run CountDownTimer in a Service in Android? 请注意,此代码来自于如何在Android中的服务中运行CountDownTimer? where I learned how to run CountDownTimer as a service. 在这里,我学习了如何将CountDownTimer作为服务运行。

I have a completely functional RecyclerView. 我有一个功能齐全的RecyclerView。 I just don't know how the logic would work using these classes to have several different timers. 我只是不知道使用这些类具有几个不同的计时器时逻辑将如何工作。

For example, if one timer hits 0:00:00, how will Android know what code block to run on the onFinish()? 例如,如果一个计时器到达0:00:00,Android将如何知道在onFinish()上运行哪个代码块?

Please note that using broadcast receiver for this type of task may be a very heavy solution and you may consider using some sort of callback interfaces. 请注意,将广播接收器用于此类任务可能是非常繁重的解决方案,您可以考虑使用某种回调接口。

Having that said, using your current solution, you can use extra's (bi.putExtra(...)) to add resources to the intents you send. 话虽如此,使用当前的解决方案,您可以使用extra的(bi.putExtra(...))将资源添加到您发送的意图中。 Then inside your receiver you can retrieve those values (get*Extra(...); ie int identifiers of the timers - just as you do with bi.putExtra("countdown", millisUntilFinished)). 然后,您可以在接收器内部检索这些值(get * Extra(...);即计时器的int标识符-就像使用bi.putExtra(“ countdown”,millisUntilFinished)一样。

Edit: 编辑:

Based on comments, I'm not entirely sure of what you would like to do, but maybe this will help: 根据评论,我不确定您要做什么,但这也许会有所帮助:

The onCreate method of the service will get called only once and should be used for general service initialization - every subsequent call to startService will only cause the onStartCommand invocation, which should be used to create your timers. 服务的onCreate方法将仅被调用一次,并且应用于常规服务初始化-每次对startService的后续调用都只会引起onStartCommand调用,该调用应用于创建计时器。

When you start your service using startService(new Intent(this, BroadcastService.class)), you can also put extras inside the intent. 当使用startService(new Intent(this,BroadcastService.class))启动服务时,还可以将其他内容放入意图中。 Then the onStartCommand(Intent intent, int flags, int startId) gets called, with intent having your extras, unique to each startService call. 然后,调用onStartCommand(Intent intent,int flags,int startId),意图是让您的附加功能对于每个startService调用都是唯一的。

Inside the onStartCommand you can retrieve extras like identifier of the timer and it's requested runtime, create a CountDownTimer and store them somewhere, eg a HashMap, where String key would be the identifier. 在onStartCommand内,您可以检索计时器标识符及其所请求的运行时等额外信息,创建一个CountDownTimer并将它们存储在某个地方,例如HashMap,其中String键将是标识符。

Inside the onTick method of each timer, you would also put an antoher value - the timer identifier, which you can retrieve on the application side, so you know which timer posted the broadcast. 在每个计时器的onTick方法内,您还将放置一个另一个值-计时器标识符,您可以在应用程序端检索该标识符,因此您知道哪个计时器发布了广播。

This way you can manage the timers on both the app and service side, using your identifier. 这样,您可以使用标识符在应用程序和服务端管理计时器。 You may want to handle a situations like starting the service with the same identifier, while the timer is still running (cancellation etc.). 您可能想处理诸如使用相同的标识符启动服务,而计时器仍在运行的情况(取消等)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM