【问题标题】:Delete files in a background thread在后台线程中删除文件
【发布时间】:2017-06-21 12:29:11
【问题描述】:

任务:我想在后台线程中从MediaStore 中删除文件,以便用户可以在线程工作时使用我的应用程序。


问题: 我知道每当一个进程完成时,它的线程也会完成它们的工作。因此,这意味着如果用户快速关闭应用程序,我将无法从MediaStore 中删除所有选定的文件,从而终止进程。

可能的解决方案:您认为将该过程作为一个单独的流程(任务)来实现是个好主意吗?例如,使用Service

代码

 Snackbar.make(findViewById(R.id.rootView),message)
                    .setAction("UNDO", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                           //restore data
                        }
                    })
                    .addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
                        @Override
                        public void onDismissed(Snackbar transientBottomBar, int event) {
                            super.onDismissed(transientBottomBar, event);
                            switch (event) {
                                case DISMISS_EVENT_SWIPE:
                                case DISMISS_EVENT_TIMEOUT:
                                    //delete the files using either a background thread, or a separate task
                                    break;
                            }
                        }
                    })
                    .show();


更新

 public static void deleteFile(Context context, File mediaFile) {
    if(!mediaFile.delete()) {
        Log.e(TAG, "Cannot delete file "+ mediaFile.getAbsoluteFile());

    }
    String[] projection = { MediaStore.Images.Media._ID };

    String selection = MediaStore.Images.Media.DATA + " = ?";
    String[] selectionArgs = new String[] { mediaFile.getAbsolutePath() };

    Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    ContentResolver contentResolver = context.getContentResolver();
    Cursor cursor = contentResolver.query(queryUri, projection, selection, selectionArgs, null);

    if(cursor!=null) {
        if (cursor.moveToFirst()) {
            long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
            Uri deleteUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
            contentResolver.delete(deleteUri, null, null);
        }
        cursor.close();
    }
}

谢谢!

【问题讨论】:

  • 有多少个文件?这个过程需要很长时间?
  • 视情况而定。它可以是 10 或 1000。基本上,用户可以删除整个文件夹的文件。
  • 删除1000个文件需要很长时间吗?特别是放在一个文件夹里。我猜您不仅要删除MediaStore,还要更新MediaStore
  • 够用了。如果我想删除 1000 个文件,然后我立即关闭应用程序,它将删除大约 10-20 个文件。
  • 是的,没错,我也在更新MediaStore。我现在将发布此过程的代码。

标签: android multithreading service android-asynctask mediastore


【解决方案1】:

是的,这听起来像是 Service 的一个很好的候选者但是当你说“作为一个单独的进程(任务)”时,这不是 Service 的含义:

服务不是一个单独的进程。 Service 对象本身并不意味着它在自己的进程中运行;除非另有说明,否则它会在与其所属的应用程序相同的进程中运行。

服务不是线程。它本身并不是一种脱离主线程工作的方法(以避免 Application Not Responding 错误)。

https://developer.android.com/reference/android/app/Service.html#WhatIsAService

这是可行的,因为用户通常不会以终止进程的方式关闭应用程序。应用程序继续运行,即使所有活动都已关闭,甚至从最近的应用程序列表中滑出。

【讨论】:

  • 是的,不是。但是,我可以将其指定为一个单独的过程,对吗?这正是我要问的,这样做值得吗?
  • 不,这会更难,而且没有任何充分的理由。请参阅我的新编辑。您可以使用现有流程,因为它在活动结束后仍然存在,尤其是在有服务运行时。
  • 如果我错了,最好有自己的进程,这显然是清单中的简单转换:stackoverflow.com/a/38318003/360211
  • 这支持了我的想法:stackoverflow.com/a/9434268/360211
  • 是的,当activity启动时,它可以显示任何正在运行的删除服务的进度,当然。在复制文件时,通知进度会像这个应用程序一样出色:play.google.com/store/apps/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-16
  • 1970-01-01
相关资源
最近更新 更多