AsyncTask: Что использовать, когда doInBackground занят? - PullRequest
0 голосов
/ 03 ноября 2018

Я должен поделиться изображением в моем приложении.

Glide.with(PhotoFullScreenActivity.this)
         .asBitmap()
         .load(getBestDownscaledAlternative(mPhotoList.get(mCurrentPosition)))
         .into(new SimpleTarget<Bitmap>() {
             @Override
             public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                 startShareImageTask(resource);
             }

             @Override
             public void onLoadFailed(@Nullable Drawable errorDrawable) {
                 super.onLoadFailed(errorDrawable);
                 Log.e("Check","error");
             }
         });

Я использую приведенный выше фрагмент для преобразования URL в растровое изображение, и после того, как ресурс готов, я вызываю startShareImageTask для создания файла.

StartShareImageTask выглядит так:

private void startShareImageTask(Bitmap resource){

    new AsyncTask<Bitmap, Void, Uri>(){

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mShareLoadingPB.setVisibility(View.VISIBLE);
            Log.d("ShareImageTask", "onPreExecute: " + System.currentTimeMillis());
        }

        @Override
        protected Uri doInBackground(Bitmap... bitmaps) {
            Uri bmpUri = null;
            try {
                // Use methods on Context to access package-specific directories on external storage.
                // This way, you don't need to request external read/write permission.
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
                FileOutputStream out = new FileOutputStream(file);
                resource.compress(Bitmap.CompressFormat.JPEG, 90, out);
                out.close();

                // wrap File object into a content provider. NOTE: authority here should match authority in manifest declaration
                bmpUri = ImageFileProvider.getUriForFile(PhotoFullScreenActivity.this, getApplicationContext().getPackageName() + ".fileprovider", file);  // use this version for API >= 24

            } catch (IOException e) {
                e.printStackTrace();
                mShareLoadingPB.setVisibility(View.GONE);
            }
            return bmpUri;
        }

        @Override
        protected void onPostExecute(Uri uri) {
            super.onPostExecute(uri);
            mShareLoadingPB.setVisibility(View.GONE);

            mShareIntent = new Intent();
            mShareIntent.setAction(Intent.ACTION_SEND);
            mShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
            mShareIntent.setType("image/*");

            startActivity(Intent.createChooser(mShareIntent, "Share image"));
        }
    }.execute();
}

Все отлично работает, но моему приложению нужно записать что-то в фоновом режиме, и когда это происходит, мой метод doInBackground не вызывается, пока я не закончу запись ... Я хочу поделиться изображением, пока я что-то записываю.

Что я могу сделать, если мой фоновый поток занят другой задачей? Есть ли обходной путь к этому?

1 Ответ

0 голосов
/ 03 ноября 2018

Мне удалось сделать эту работу, изменив AsyncTask на RxJava. Я оставлю здесь разницу в коде на случай, если кто-нибудь столкнется с этой проблемой.

 mShareLoadingPB.setVisibility(View.VISIBLE);
    Log.d("ShareImageTask", "onPreExecute: " + System.currentTimeMillis());

    Observable.fromCallable(() -> {
        Uri bmpUri = null;
        try {
            // Use methods on Context to access package-specific directories on external storage.
            // This way, you don't need to request external read/write permission.
            File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
            FileOutputStream out = new FileOutputStream(file);
            resource.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.close();

            // wrap File object into a content provider. NOTE: authority here should match authority in manifest declaration
            bmpUri = ImageFileProvider.getUriForFile(PhotoFullScreenActivity.this, getApplicationContext().getPackageName() + ".fileprovider", file);  // use this version for API >= 24

        } catch (IOException e) {
            e.printStackTrace();
            mShareLoadingPB.setVisibility(View.GONE);
        }
        return bmpUri;
    })
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new DefaultObserver<Uri>() {
                @Override
                public void onNext(Uri uri) {
                    mShareLoadingPB.setVisibility(View.GONE);

                    mShareIntent = new Intent();
                    mShareIntent.setAction(Intent.ACTION_SEND);
                    mShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
                    mShareIntent.setType("image/*");

                    startActivity(Intent.createChooser(mShareIntent, "Share image"));
                }

                @Override
                public void onError(Throwable e) {
                    Log.e("Error","Error");
                }

                @Override
                public void onComplete() {

                }
            });
...