android - 长延迟AsyncTask并重新启动任务

标签 android android-asynctask

我想实现这个功能: 当用户单击按钮时启动任务,并在 5 分钟后将一个文件发送到 Dropbox,但如果用户再次单击该按钮,则先前的任务将中止并开始新任务(5 分钟)。

我编写了将文件上传到 Dropbox 的代码,但从未编写过使用时间如此长(5 分钟)的任务的代码。 怎么才能做到这一点?

--编辑--

感谢@xdevs23,我已经实现了最终的代码

public void onSendOrder() {

        try {
            mHandler.removeCallbacks(postRunnable); // stop current wait
        } catch(Exception ex) {
            // Just if the above fails (might be first time)
            ex.printStackTrace();
        }
        int minutes = 5;
        mHandler.postDelayed(postRunnable, minutes * 20 * 1000 /* 5 minutes in milliseconds */);
...
...
...

private Runnable postRunnable = new Runnable() {
        @Override
        public void run() {
            Thread myThread = new Thread(myRunnable);
            myThread.start();
        }
    };


    private Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                // your code
                int cloud = GetPreferenceCloud();
                if(cloud > 0){
                    ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
                    final File bckDatabase = BackupDatabase();

                    if (networkInfo != null && networkInfo.isConnected() && bckDatabase != null) {

                    runOnUiThread(new Runnable() {
                        public void run() {
                            // call your asynctask here
                            new UploadOnCloud(MainActivity.this,
                                    PreferenceConstants.DB_DATABASE_STORE_CLOUD,
                                    PreferenceConstants.FILE_DIR_CLOUD,
                                    bckDatabase,
                                    mUListener,
                                    cloud).execute();
                        }
                    });

                } else {
                        Toast.makeText(getContext(),getContext().getResources().getString(R.string.send_msg13), Toast.LENGTH_SHORT).show();
                    }
                }
            }
        };

* 编辑。 V2 *

为了在状态栏上实现倒计时,我已经实现了:

修改onSend函数:

public void onSendOrder() {

        try {
            mHandler.removeCallbacks(postRunnable); // stop current wait
        } catch(Exception ex) {
            // Just if the above fails (might be first time)
            ex.printStackTrace();
        }
        minute = 3600;
        //mHandler.postDelayed(postRunnable, minutes * 20 * 1000 /* 5 minutes in milliseconds */);
        mHandler.postDelayed(postRunnable, 1000 /* 1 seconds */);

.... ....

在文件 menu.xml 中

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/break_timer"
          android:title="00:00"
          app:showAsAction="always"
          app:actionViewClass="android.widget.TextView" />
    <item
        android:id="@+id/action_refresh"
        android:title="@string/action_refresh"
        app:showAsAction="ifRoom"
        android:icon="@drawable/ic_action_autorenew"/>
</menu>

修改onCreateOptionsMenu

 public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.main, menu);
        MenuItem timerItem = menu.findItem(R.id.break_timer);
        timerText = (TextView) MenuItemCompat.getActionView(timerItem);
        timerText.setPadding(10, 0, 10, 0); //Or something like that...

        return super.onCreateOptionsMenu(menu);
    }


private int minute;
    private Runnable postRunnable = new Runnable() {
        @Override
        public void run() {
            if(minute >= 0){
                minute--;
                mHandler.postDelayed(postRunnable, 1000 /* 1 seconds */);
                timerText.setText(secondsToString(minute));
            }else {
                Thread myThread = new Thread(myRunnable);
                myThread.start();
            }
        }
    };

最佳答案

您可以使用ThreadRunnable来代替使用AsyncTask

创建一个Runnable,您要在后台运行的代码所在的位置:

Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        // your code
    }
}

创建您的线程:

private Thread myThread;

确保您在主线程上创建了一个处理程序。 为了获得最佳结果,请将其添加到您的 onCreate() 方法中:

private Handler mHandler;

@Override
public void onCreate() {
    // ...
    mHandler = new Handler();
    // ...
}

您需要导入android.os.Handler

声明上传代码所在的可运行程序:

private Runnable postRunnable = new Runnable() {
    @Override
    public void run() {
        Thread myThread = new Thread(myRunnable);
        myThread.start();
    }
}

现在,当用户单击按钮时执行以下操作:

try {
    mHandler.removeCallbacks(postRunnable); // stop current wait
} catch(Exception ex) {
    // Just if the above fails (might be first time)
}
int minutes = 5;
mHandler.postDelayed(postRunnable, minutes * 60 * 1000 /* 5 minutes in milliseconds */);

就是这样。

说明:

当用户点击按钮时,它将等待(不阻塞 UI)5 秒,然后它将运行 postRunnable 内的代码,从而在后台启动一个新线程,它将运行 myRunnable 中的代码。

编辑更新通知

private Handler mHandler;
private int minutes = 5;
private Runnable updateRunnable = new Runnable() {
    @Override
    public void run() {
        if(minutes > 0) {
            String notifContent = "" + minutes + " remaining.";
            // Create your notification (there are several guides which show you how to do this), use notifContent as title or text or whatsoever
            minutes--;
            mHandler.postDelayed(updateRunnable, 60 * 1000);
        } else {
            // Remove your notification
        }
    }
};

开始倒计时:

mHandler.post(updateRunnable);

关于android - 长延迟AsyncTask并重新启动任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38411095/

相关文章:

android - 仪器测试 : define a test as mandatory for the following

android - 没有gradle的缓存版本-不禁用离线模式

java - Fragment 启动时 OnClickListeners 不会触发

android - 在 TabActivity 的 FrameLayout 内启动另一个 Activity

java - AsyncTask : ClassCastException: java. lang.Object[] 无法转换为 java.lang.String[]

android - ProgressDialog 没有出现在 AsyncTask 中

android - 在 fragment 中使用asynctask

android - Interceptor.Chain.proceed() 是线程阻塞方法吗?

java - 无法将textView文本从MainActivity(第一个 Activity )传递到UserprofileActivity(第二个 Activity )

java - 如何将对象从asynctask返回到android中的主类