服务+AsyncTask - 如何真正停止任务?

问题描述 投票:0回答:1

我在结束AsyncTask时遇到了麻烦,尽管我已经遵守了推荐的标志做法。下面的代码只考虑到了BackButton,但如果能有一个通用的解决方案来解决所有类型的退出活动,那将是最好的。

我有一个MeasurementLoadingsScreen类,它绑定了一个这样的Service。

ServiceConnection _connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            _service = myService.Stub.asInterface(iBinder);
            runMeasurementAsyncTask();
        }

        public void onServiceDisconnected(ComponentName componentName) {
            _service = null;
        }
    };

 @Override
    protected void onStart() {
        super.onStart();
        Intent serviceIntent = new Intent();
        serviceIntent.setPackage(myService.class.getPackage().getName());
        serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
        bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
    }

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_measurement_loadingscreen);
        findViewsById();
        setDefaultVisibility();

        intent = getIntent();
       //myStuff
    }

MeasurementLoadingScreen包含一个带有WeakReference(或SoftReference,两种都试过)的AsyncTask。

private void runMeasurementAsyncTask() {
 //myStuff
        meTask = new MeasurementTask(this);
        meTask.execute();
    }

private static class MeasurementTask extends AsyncTask<Integer, Integer, String> {
        private WeakReference<MeasurementLoadingScreen> activityReference;
        private ServiceHelper serviceHelper;
       //myStuff
        public static boolean isRunning = false;


        MeasurementTask(MeasurementLoadingScreen context) {
            activityReference = new WeakReference<>(context);
            serviceHelper = new ServiceHelper(context._service);
        }

        @Override
        protected String doInBackground(Integer... params) {
            MeasurementLoadingScreen activityReference = this.activityReference.get();
            isRunning = true;
            //myStuff, it's ok to finish running this before cancelling
            if (isCancelled()) {
                return "cancelled";
            }
            // more myStuff
            if (isCancelled()) {
                return "cancelled";
            }

           [...]

 @Override
        protected void onCancelled(){
          //myStuff: safely shutdown measurement process, might take a few seconds at worst
            meTask.isRunning = false;

            if(activityReference.get() != null) {
                activityReference.get().finish();  //it does not work without this, either
            }
          super.onCancelled();
        }

当我向后点两次(不管具体行为如何),它应该(安全地)中止AsyncTask。

  @Override
    public void onBackPressed()
    {
        if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
        {
            if (meTask == null) {
                super.onBackPressed();
                return;
            }
            cancelTask();
            Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
            return;
        }
        else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }

        mBackPressed = System.currentTimeMillis();
    }
    @Override
    protected void onStop() {
        super.onStop();
        if (_connection != null)
        unbindService(_connection);
        finish();//
    }

    @Override
    public void onPause() {
        int i = 0;
        super.onPause();
//poll state of task here
        finish();
    }

我似乎无法让任务停止运行。例如,如果我在onPause中设置meTask =null;,它最终会通过onCancelled,然后调用onStop,也结束服务。但是没有办法等onCancelled做完它的事情,然后用isRunningflag,getStatus或者其他什么东西来通知我。无论我如何轮询任务,这个应用都会冻结,而任务一直处于RUNNING状态,除非我把它设置为null(当然,这是不可取的)。

编辑:我已经添加了一个轮询尝试,让活动最终调用onPauseonStop,但我的主要问题是轮询,我从来没有看到一个finishfinishing任务,即使onCancelled在某些时候被调用,但只有在我设置meTask=null;之后,它才会正常继续取消。

public void onBackPressed() {
        int i=0;
        if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
        {
            if (meTask == null) {
                super.onBackPressed();
                return;
            }
            cancelTask();
            Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
            while ((meTask.getStatus()== AsyncTask.Status.RUNNING) && (i < 20000)) {
//waiting etc., checking für isRunning doesn't work either
                i++;
            }
            Log.d(TAG, "meTask  " + meTask.getStatus());
            meTask = null;
            Log.d(TAG, "meTask null after " + i);
            super.onBackPressed();
            return;

Edit 2:
Content of cancelTask()
private void cancelTask() {
        if (meTask != null) {
            Log.d(TAG, "Async Task Cancel... ");
            meTask.cancel(true);
        }
    }

编辑3:无论我把cancel(true)放在哪里,比如onPause,onStop,Task都会保持活力,并且只给我输出了以下的Log

    if (isCancelled()) {
            Log.d(TAG, "Cancel after XYZ");
            return "cancelled";
    }

@Override
        protected void onCancelled() {
            super.onCancelled();
            isRunning = false;
            Log.d(TAG, "...Async Task Cancelled ");
        }

在最后,在onPause,onStop,onDestroy完成后。我束手无策。任务继续运行一会并不奇怪,但它必须在服务解绑前停止。如何才能等待任务结束?

android android-asynctask android-service
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.