Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Android中持续更新UI线程的最有效方法_Java_Android_Multithreading_Android Asynctask - Fatal编程技术网

Java 在Android中持续更新UI线程的最有效方法

Java 在Android中持续更新UI线程的最有效方法,java,android,multithreading,android-asynctask,Java,Android,Multithreading,Android Asynctask,我正在通过创建秒表来尝试Android开发中的线程。我目前有一个非常基本的执行,它在模拟器上似乎运行得很好,但在我的手机上运行时却没有效率(非常新的Nexus6,所以手机很好)。我的问题是,作为秒表,持续更新UI线程最有效的方法是什么 我目前正在一个更新UI onProgressUpdate的异步任务中运行它。我想AsyncTask并不是最好的选择,但我也在自己的Runnable中尝试过,结果更糟。我读过关于Handler类的文章,但对如何使用它(或者知道它是否是答案)没有信心。下面是我创建和执

我正在通过创建秒表来尝试Android开发中的线程。我目前有一个非常基本的执行,它在模拟器上似乎运行得很好,但在我的手机上运行时却没有效率(非常新的Nexus6,所以手机很好)。我的问题是,作为秒表,持续更新UI线程最有效的方法是什么

我目前正在一个更新UI onProgressUpdate的异步任务中运行它。我想AsyncTask并不是最好的选择,但我也在自己的Runnable中尝试过,结果更糟。我读过关于Handler类的文章,但对如何使用它(或者知道它是否是答案)没有信心。下面是我创建和执行AsyncTask以及AsyncTask本身的地方。我应该注意到这是一个片段

// Where the thread kicks off on click
private class StartTimer implements View.OnClickListener{
    @Override
    public void onClick(View v) {
        // passes the stopWacth object and the view to update
        clockThread = new HiitClock(clockTv, stopWatch);
        clockThread.execute();
    }
}
然后,这是我扩展AsyncTask的类

public class HiitClock extends AsyncTask<String, Void, String> {

    private final String LOG_TAG = HiitClock.class.getSimpleName();
    private TextView clock;
    private StopWatch stopWatch;

    public HiitClock(TextView clock, StopWatch sw){
        this.clock = clock;
        this.clockSegment = clockSegment;
        this.roundSegment = roundSegment;
        this.stopWatch = sw;
    }


    @Override
    protected String doInBackground(String... params) {

        stopWatch.start();

        while(stopWatch.getState() == 1 || stopWatch.getState() == 2){
            publishProgress();
        }

        return "done";
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);

        clock.setText(convertTime());
    }

    @Override
    protected void onPostExecute(String result) {
        // end of timer
       clock.setText(result);
    }

    /*
    * helper method for converting the time
    * */
    private String convertTime(){

        long milli = stopWatch.getTime();
        long sec = milli / 1000 ;
        long min = sec / 60;
        sec = sec % 60;
        milli = milli % 100;

        return String.format("%02d:%02d:%02d", min, sec, milli);
    }
}
公共类HiitClock扩展异步任务{
私有最终字符串LOG_TAG=HiitClock.class.getSimpleName();
专用文本视图时钟;
私人秒表;
公共HiitClock(文本视图时钟、秒表开关){
这个时钟=时钟;
this.clockSegment=clockSegment;
this.roundSegment=roundSegment;
这个。秒表=sw;
}
@凌驾
受保护的字符串doInBackground(字符串…参数){
秒表。开始();
while(stopWatch.getState()==1 | | stopWatch.getState()==2){
出版进度();
}
返回“完成”;
}
@凌驾
受保护的void onProgressUpdate(void…值){
super.onProgressUpdate(值);
clock.setText(convertTime());
}
@凌驾
受保护的void onPostExecute(字符串结果){
//计时器结束
clock.setText(结果);
}
/*
*转换时间的辅助方法
* */
私有字符串转换时间(){
long milli=秒表。getTime();
长秒=毫/千;
长最小值=秒/60;
秒=秒%60;
毫=毫%100;
返回字符串。格式(“%02d:%02d:%02d”,分钟,秒,毫秒);
}
}
-------更新---------

我感谢各位的答复。我尝试了所有的建议,但在真正的设备上性能仍然很差。我在下面创建了一个简单的示例。也许这个简单的版本可以帮助人们了解我在做什么,阻止UI线程高效地更新。它循环100000次,并使用处理程序尝试和更新UI线程。谢谢

public class MainActivity extends Activity {

    private RelativeLayout wrapper;
    private TextView clockTv;
    private Handler handler;

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

        handler = new Handler();
        wrapper = (RelativeLayout) findViewById(R.id.hitt_cardio_layout);
        clockTv = (TextView) wrapper.findViewById(R.id.clock_text_view);

        Button start = new Button(this);
        start.setText("Start");
        wrapper.addView(start);
        start.setOnClickListener(new StartTimer());

    }

    private class StartTimer implements View.OnClickListener {

        @Override
        public void onClick(View v) {

            new Thread(new Runner()).start();

        }

    }

    private class Runner implements Runnable{
        int i;
        @Override
        public void run() {
            for(i = 0; i < 100000; i++){
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        clockTv.setText("index: " + i);
                    }
                });
            }
        }
    }
}
公共类MainActivity扩展活动{
私有相对论包装;
私人文本视图时钟电视;
私人经办人;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler=新的handler();
wrapper=(相对)findViewById(R.id.hitt\u cardio\u布局);
clockTv=(TextView)wrapper.findviewbyd(R.id.clock\u text\u view);
按钮启动=新按钮(此按钮);
start.setText(“开始”);
wrapper.addView(开始);
setOnClickListener(newstarttimer());
}
私有类StartTimer实现View.OnClickListener{
@凌驾
公共void onClick(视图v){
新线程(新流道()).start();
}
}
私有类运行器实现可运行{
int i;
@凌驾
公开募捐{
对于(i=0;i<100000;i++){
handler.post(新的Runnable(){
@凌驾
公开募捐{
clockTv.setText(“索引:+i”);
}
});
}
}
}
}

您可以使用onProgressUpdate()更新UI。除此之外,还有两种方法:

  • 使用活动的runOnUiThread方法:

      Activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //update your UI
                    }
                });
    
  • 您还可以使用处理程序:

    Handler h = new Handler(){
      @Override
      public void handleMessage(Message msg){
         if(msg.what == 0){
            updateUI();
         }else{
            showErrorDialog();
         }
      }
    };
    

  • 您可以在更新视图的线程上发布runnable:

    clock.post(new Runnable() {
        @Override public void run() {
            clock.setText(convertTime());
            // 50 millis to give the ui thread time to breath. Adjust according to your own experience
            clock.postDelayed(this, 50);
        }
    });
    

    (为了保持示例简短,我省略了停止逻辑。将其放回去是一个测试问题,而不是重新发布runnable)。

    您正在使用onProgressUpdate更新UI线程,对吗?这有什么问题?或者,您也可以使用runOnUIThread方法。异步任务的优先级非常低,因此可能会暂停以将处理器时间分配给另一个线程。由于您根本不需要后台线程,因此自动重新输入
    runOnUiThread
    效率更高,我非常感谢您的回复。不幸的是,一切似乎都不起作用。我在上面添加了一个更简单的版本,可能有助于确定问题是什么。谢谢,经过更多的测试和研究,我发现你的答案就是我的解决方案。特别是postdayed()方法。最后,我使用了一个Handler对象和postDelayed,并且尽可能地平滑。