Android 使用处理程序每​​ 10 秒调用一次方法

Android call method every 10 seconds with handler

我想每 10 秒用一个计时器调用我的函数,我的函数有一个处理程序,它显示错误:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

我的函数:

 public void startData(){
 doBindService();
 new Handler().post(mQueueCommands);
 }

这个 startData() 有一个 public 变量 "btIsConnected" ,每当 btIsConnected== true,我想停止调用它,否则前两分钟我想每 10 秒调用一次 startData()

class startLiveDataTimerTask extends TimerTask{
    public void run(){
        startData();   
    }
}

private void tryConnectEveryTenSeconds() {
    Timer timer = new Timer();
    timer.schedule(new startLiveDataTimerTask(), 0, 10000);
}

onCreate() 中:

long futureTimeInTwoMinute = System.currentTimeMillis() + 120000;

Intent i = new Intent(ObdConstants.StartLiveData.getValue()); sendBroadcast(i);   // this broadcaster is used to call StartData() for the first time

    if(System.currentTimeMillis()<futureTimeInTwoMinute){
//  how do I make a time counter appropriately?
        if(btIsConnected){
            Log.d(TAG, "is connected!");
            //do nothing
        }else{
            Log.d(TAG, "try to connect every ten seconds....");
            tryConnectEveryTenSeconds();
        }
    }

只能在 Looper 中的线程上创建处理程序。 UI 主线程在 Looper 中,因此可以在那里创建处理程序。普通的 Thread 或 AsyncTask 不是,因此它们无法创建 Handlers。假设你想post到UI线程,你需要在UI线程上创建Handler。

顺便说一句,看到这样创建新处理程序的代码非常不寻常。通常,模式是在构造函数中创建一个 Handler 并向其 post 。像这样创建新的处理程序充其量是低效的,最坏的情况是错误。

如果要使用Handler架构,Timer对象就没有用了。

首先,获取Handler。对于示例,我将使用主 Handler (UIThread),但您也可以使用新的 Looper.

创建自己的

所以,让我们像这样开始循环任务:

private void tryConnectEveryTenSeconds() {
    Handler handler = new Handler(Looper.getMainLooper()); //This gets the UIThread Handler
    handler.postDelayed(new startLiveDataTimerTask(), 10000); //This posts the task ONCE, with 10 sec delay
}

现在开始任务:

public void startData(){
     doBindService();
     Handler handler = new Handler(Looper.getMainLooper());
     handler.post(mQueueCommands); //I expect this is what you want. If not and you want a completely new Handler, you will need to create it on a new Thread
     handler.postDelayed(new startLiveDataTimerTask(), 10000); //This posts the task AGAIN, with 10 seconds delay     
}

请注意,所有方法都将在 UIThread 上调用。如果您希望 mQueueCommands 任务在新线程上的新 Handler 上 运行,则需要创建它。


编辑:

调用代码应如下所示:

long futureTimeInTwoMinute = System.currentTimeMillis() + 120000;

Intent i = new Intent(ObdConstants.StartLiveData.getValue()); sendBroadcast(i);
tryConnectEveryTenSeconds();
while(System.currentTimeMillis()<futureTimeInTwoMinute){
    if(btIsConnected){
        Log.d(TAG, "is connected!");
        //do nothing
    }else{
        Log.d(TAG, "Not connected yet...");
    }
}

您不想多次触发循环方法:-)