简体   繁体   English

销毁后,AsyncTask 不会在恢复片段中更新我的文本视图

[英]AsyncTask does not updating my textview in resume fragment after destroy

I am running a thread in background contains timer and I display this timer in TextView but when I change current fragment and I return the timer still running in logcat but does not update in UI我在后台运行一个包含计时器的线程,我在TextView中显示这个计时器,但是当我更改当前片段并返回仍在logcat中运行但不在 UI 中更新的计时器时

My code:我的代码:

final Runnable r = new Runnable() {
            public void run() {
                if (mBound) {
                    long elapsedTime = stopWatchService.getElapsedTime();
                    formattedTime = DateUtils.formatElapsedTime(elapsedTime);
                    Log.i(TAG, "formattedTime "+ formattedTime);
                    textView.setText(formattedTime);
                }
            }
        };
 Task task = new Task(r);
 task.execute((Void) null);

My task:我的任务:

public class Task extends AsyncTask<Void, Void, Void> {


        private static final String TAG = "Task";

        private boolean mPaused;

        private Runnable mRunnable;

        public Task(Runnable runnable, TextView textView) {
            mRunnable = runnable;
            play();


        }

        @Override
        protected Void doInBackground(Void... params) {
            while (!isCancelled()) {
                if (!mPaused) {

                    mRunnable.run();
                    sleep();
                }
            }
            return null;
        }

        private void sleep() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Log.w(TAG, e.getMessage());
            }
        }

        public void play() {
            mPaused = false;
        }

        public void pause() {
            mPaused = true;
        }

        public void stop() {
            pause();
            cancel(true);
        }

        public boolean isPaused() {
            return mPaused;
        }
}

My service:我的服务:

public class StopWatchService extends Service {

    private String TAG = "walkingApp";
    StopWatch stopWatch = new StopWatch();

    public StopWatchService() {

    }

    public class LocalBinder extends Binder {
        public StopWatchService getService() {
            return StopWatchService.this;
        }
    }

    private final IBinder mBinder = new LocalBinder();


    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /*
    When the service is started, start stopwatch.
     */
    public int onStartCommand(Intent intent, int flags, int startId) {
        stopWatch.start();


        return START_STICKY;
    }

    /* return how much time has passed in seconds */
    public long getElapsedTime() {
        return stopWatch.getElapsedTime();
    }


    @Override
    public boolean stopService(Intent name) {
        stopWatch.stop();
        return super.stopService(name);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
       // stopWatch.stop();
    }
}

AsyncTask was deprecated a few years ago, which was, IMHO, long overdue. AsyncTask 几年前就被弃用了,恕我直言,早就该弃用了。 It had lots of problems, like the one you are encountering, and only really ever worked well in some very special cases.它有很多问题,就像你遇到的那个,而且只有在一些非常特殊的情况下才能真正发挥作用。

There are several other ways to handle this situation, including, but not limited to RxJs, executors, and Kotlin Coroutines.还有其他几种方法可以处理这种情况,包括但不限于 RxJs、executor 和 Kotlin Coroutines。

Have a look at The AsyncTask API is deprecated in Android 11. What are the alternatives?查看Android 11 中弃用的 AsyncTask API。有哪些替代方案?

The short answer here is probably that you use a Chronometer instead of a TextView .这里的简短回答可能是您使用Chronometer而不是TextView Then all you need to do is set the start time once , and the you no longer need to worry about keeping track of what time to display yourself.然后您需要做的就是设置一次开始时间,您不再需要担心跟踪显示自己的时间。 You can get rid of your timer.你可以摆脱你的计时器。 For example (very naive approach):例如(非常天真的方法):

public class MyActivityOrFragment ... {

  //Start time as "uptime"
  private static final AtomicLong base = 
    new AtomicLong(SystemClock.uptimeMillis());

  @Override
  public void onStart() {
    //...
    chronometer.setBase(base.get());
  }

}

If you want to change this base time whilst the Activity/Fragment is open, then you can get do it in plenty of ways.如果您想在 Activity/Fragment 打开时更改此基准时间,则可以通过多种方式进行。 You could send an intent with the base time as an extra, use an interface, an event bus, monitor a database, etc.您可以额外发送带有基本时间的意图、使用接口、事件总线、监控数据库等。

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

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