在Android中取消并再次启动AsyncTask

时间:2016-10-16 20:32:39

标签: android android-fragments android-asynctask

第一次取消任务后,我无法启动任务。它将在进入视图时运行,并启动任务,然后在首次销毁片段时取消。但是当重新进入视图时,AsyncTask将不再运行。

是否有可能需要清理一些类状态?或者我是否需要从后堆栈中删除Fragment AsyncTask

以下是我的代码:

package com.emijit.lighteningtalktimer;

import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.emijit.lighteningtalktimer.data.Timer;
import com.emijit.lighteningtalktimer.data.TimerContract.TimerEntry;


public class RunTimerFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final String LOG_TAG = RunTimerFragment.class.getSimpleName();

    private View rootView;
    private Uri mUri;
    private long mTimerId = 0;
    private Timer mTimer;
    private RunTimerTask mRunTimerTask;

    private static final int DETAIL_LOADER = 0;

    public static String URI = "URI";

    public RunTimerFragment() {
    }

    static class ViewHolder {
        TextView intervals;
        TextView timerSeconds;
        TextView timerMinutes;
        TextView timerHours;

        public ViewHolder(View view) {
            intervals = (TextView) view.findViewById(R.id.run_timer_intervals);
            timerSeconds = (TextView) view.findViewById(R.id.timer_seconds);
            timerMinutes = (TextView) view.findViewById(R.id.timer_minutes);
            timerHours = (TextView) view.findViewById(R.id.timer_hours);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_run_timer, container, false);

        ViewHolder viewHolder = new ViewHolder(rootView);
        rootView.setTag(viewHolder);

        Bundle arguments = getArguments();
        if (arguments != null) {
            mUri = arguments.getParcelable(URI);
            if (mUri != null) {
                mTimerId = ContentUris.parseId(mUri);
                Log.d(LOG_TAG, "mTimerId: " + mTimerId);
            }
        }

        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(DETAIL_LOADER, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (mTimerId != 0) {
            return new CursorLoader(
                    getActivity(),
                    TimerEntry.CONTENT_URI,
                    null,
                    TimerEntry._ID + " = ?",
                    new String[] { Long.toString(mTimerId) },
                    null
            );
        }
        return null;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        if (cursor != null && cursor.moveToFirst()) {
            mTimer = new Timer(cursor);
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }

    public void startTimer() {
        mRunTimerTask = new RunTimerTask();
        mRunTimerTask.execute(mTimer);
    }

    @Override
    public void onPause() {
        super.onPause();
        mRunTimerTask.cancel(true);
    }

    private class RunTimerTask extends AsyncTask<Timer, Integer, Long> {

        private final String LOG_TAG = RunTimerTask.class.getSimpleName();

        Timer mTimer;
        int mCurrentSeconds = 0;
        int mCurrentIntervals = 0;

        @Override
        protected Long doInBackground(Timer... params) {
            Log.d(LOG_TAG, "doInBackground");
            mTimer = params[0];

            while (mTimer.getIntervals() > mCurrentIntervals) {
                try {
                    Thread.sleep(1000);
                    mCurrentSeconds++;
                    publishProgress(mCurrentSeconds);
                } catch (InterruptedException e) {
                    Log.d(LOG_TAG, e.toString());
                }
            }
            return (long) mCurrentIntervals;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // do stuff
        }


        @Override
        protected void onPostExecute(Long aLong) {
            super.onPostExecute(aLong);
            Log.d(LOG_TAG, "onPostExecute");
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我认为问题可能出在catch块中。不确定mTimer.getIntervals(),因为它来自第三方。

取消任务时。 InterruptedException将在任务线程中捕获。然后你的循环仍将继续,因为你没有返回或打破循环。

由于所有AsyncTask都将在一个大小为1的线程池中排队,即使你启动另一个AsyncTask,它仍然会被阻塞。

答案 1 :(得分:0)

在您的示例中,我看不到对startTimer()的任何调用。你应该覆盖onResume()并在那里调用startTimer()吗?