Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RejectedExecutionException crashes #118

Closed
stonelai opened this issue Sep 2, 2017 · 4 comments
Closed

RejectedExecutionException crashes #118

stonelai opened this issue Sep 2, 2017 · 4 comments

Comments

@stonelai
Copy link

stonelai commented Sep 2, 2017

My Google Console reports dozens of RejectedExecutionException crashes with the version of 1.6.

===========================================

Samsung Galaxy J5(2016) (j5xnlte), 2048MB RAM, Android 6.0
Report 1 of 9

java.lang.RuntimeException:
at android.app.ActivityThread.deliverResults (ActivityThread.java:4927)
at android.app.ActivityThread.handleSendResult (ActivityThread.java:4970)
at android.app.ActivityThread.access$1600 (ActivityThread.java:223)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1851)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:158)
at android.app.ActivityThread.main (ActivityThread.java:7231)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)

Caused by: java.util.concurrent.RejectedExecutionException:
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution (ThreadPoolExecutor.java:2014)
at java.util.concurrent.ThreadPoolExecutor.reject (ThreadPoolExecutor.java:794)
at java.util.concurrent.ThreadPoolExecutor.execute (ThreadPoolExecutor.java:1340)
at java.util.concurrent.AbstractExecutorService.submit (AbstractExecutorService.java:82)
at java.util.concurrent.Executors$DelegatedExecutorService.submit (Executors.java:594)
at com.isseiaoki.simplecropview.CropImageView.loadAsync (CropImageView.java:1438)
at com.isseiaoki.simplecropview.LoadRequest.execute (LoadRequest.java:40)
at com.threesumatch.Components.compCrop.loadImage (compCrop.java:212)
at com.threesumatch.Fragments.FragmentMe.onActivityResult (FragmentMe.java:981)
at android.app.Activity.dispatchActivityResult (Activity.java:7162)
at android.app.ActivityThread.deliverResults (ActivityThread.java:4923)

@igreenwood
Copy link
Owner

Hi,

Can you send me your Activity and Fragment code?

@stonelai
Copy link
Author

stonelai commented Sep 3, 2017

compCrop.java
-- used as a popupwindow for cropping images

public class compCrop extends LinearLayout {
private PopupWindow _popup;
private LinearLayout _popView;
private FragmentMe _fragment;
private static final int REQUEST_SAF_PICK_IMAGE = 10012;
private ImageView _pickBtn;
private ImageView _leftBtn;
private ImageView _rightBtn;
private compImageRotator _cropBtn;
private compImageRotator _doneBtn;

private Uri _uri;
private ImageView _imgPreview;
private CropImageView _imgSource;
private String _mode;
private Bitmap _bitmap;

private int _maxWidth;

private Drawable _clearDraw;
private Drawable _cropDraw;
private final String Tag_ShowCrop = "Tag_ShowCrop";
private final String Tag_ShowPreview = "Tag_ShowPreview";

public compCrop(Context _context, AttributeSet _attrs) {
    super(_context, _attrs);
}

public void start(dsFragment _frag, Intent _intent, final String _type){
    _popup = new PopupWindow(this, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, true);
    _popup.showAtLocation(this, Gravity.CENTER, 0, 0);
    this._fragment = (FragmentMe)_frag;
    this._popView = this;

    _clearDraw = _fragment.getActivity().getDrawable(R.drawable.ic_clear_white_24dp);
    _cropDraw = _fragment.getActivity().getDrawable(R.drawable.ic_crop_white_24dp);

    _imgSource =  findViewById(R.id.crop_image_source);
    _imgPreview =  findViewById(R.id.crop_image_preview);

    compHeader _header =  findViewById(R.id.header);
    _header.getBackImage().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          _popup.dismiss();
            _fragment._compCropView = null;
        }
    });

    _doneBtn = _header.getDoneImage(View.VISIBLE);
    _doneBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (Objects.equals(_cropBtn.getDrawable(), _clearDraw)) {
                if (_bitmap != null) {
                    if (!_doneBtn.isRotating()) {
                        _doneBtn.start(R.drawable.ic_autorenew_white_24dp);
                        _fragment._bitmap = _bitmap;
                        String[] _strs = {String.valueOf(AsyncRequestTypes.Convert_Bitmap_To_Base64), ""};
                        _fragment.onTaskCompleted(_strs);
                    }
                } else {
                    _fragment.showCompAlert(_popView, "No photo is cropped! Please try again.");
                }
            } else {
                _fragment.showCompAlert(_popView, "Please click the Crop button at the bottom-right corner of the screen to create a cropped photo before saving.");
            }
        }
    });

    _cropBtn = findViewById(R.id.crop_btn_preview);
    _cropBtn.setImageDrawable(_cropDraw);
    _cropBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!_cropBtn.isRotating()) {
                Drawable _currentdraw = _cropBtn.getDrawable();
                if (Objects.equals(_currentdraw, _clearDraw)) {
                    showHideImages(Tag_ShowCrop);
                } else if (Objects.equals(_currentdraw, _cropDraw)) {
                    showHideImages(Tag_ShowPreview);
                    _cropBtn.start(R.drawable.ic_autorenew_white_24dp);
                    _imgSource.setCompressFormat(Bitmap.CompressFormat.JPEG);
                    _imgSource.setCompressQuality(100);
                    Bitmap _temBitmap = _imgSource.getCroppedBitmap();
                    double _widthRatio = _temBitmap.getWidth() / _temBitmap.getHeight();
                    double _heightRatio = _temBitmap.getHeight() / _temBitmap.getWidth();
                    if (Objects.equals(_mode, CropAttrs.Profile_Icon)) {
                        showHideImages(Tag_ShowPreview);
                        if (_temBitmap.getWidth() == _maxWidth) {
                            _bitmap = _temBitmap;
                            _cropBtn.stop();

                        } else {
                            _imgSource.setOutputWidth(_maxWidth);
                            _imgSource.crop(_uri).execute(mCropCallback);
                        }
                    } else {
                        if (_widthRatio >= 2.0) {
                            _fragment.showCompAlert(_popView, "Your cropped image is too wide.");
                            _cropBtn.stop();
                            return;
                        }
                        if (_heightRatio >= 2.0) {
                            _fragment.showCompAlert(_popView, "Your cropped image is too narrow.");
                            _cropBtn.stop();
                            return;
                        }
                        showHideImages(Tag_ShowPreview);
                        if (_temBitmap.getWidth() >= _temBitmap.getHeight()) {
                            _imgSource.setOutputWidth(_maxWidth);
                        } else {
                            _imgSource.setOutputHeight(_maxWidth);
                        }
                        _imgSource.crop(_uri).execute(mCropCallback);
                    }
                }
            }
        }
    });

    _pickBtn = findViewById(R.id.crop_btn_pick);
    _pickBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            _imgSource.setImageDrawable(null);
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.setType("image/*");
            _fragment.startActivityForResult(intent, AsyncRequestTypes.Local_Request_Photo);
        }
    });

    _leftBtn =  findViewById(R.id.crop_btn_left);
    _leftBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            _imgSource.rotateImage(CropImageView.RotateDegrees.ROTATE_M90D);
        }
    });

    _rightBtn = (ImageView) findViewById(R.id.crop_btn_right);
    _rightBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            _imgSource.rotateImage(CropImageView.RotateDegrees.ROTATE_90D);
        }
    });

    switch (_type) {
        case CropAttrs.Profile_Icon:
            _header.setTitle("Upload/Update Icon");
            _imgSource.setCropMode(CropImageView.CropMode.SQUARE);
            _maxWidth = 500;
            break;
        case CropAttrs.Profile_Private_Photo:
            _header.setTitle("Upload Private Photo");
            _imgSource.setCropMode(CropImageView.CropMode.FREE);
            _maxWidth = 600;
            break;
        case CropAttrs.Profile_Public_Photo:
            _header.setTitle("Upload Public Photo");
            _imgSource.setCropMode(CropImageView.CropMode.FREE);
            _maxWidth = 600;
            break;
        default:
            break;
    }
    _imgSource.startLoad(Utils.ensureUriPermission(_fragment.getActivity().getApplicationContext(), _intent), null);
}

public void loadImage(Intent _intent)
{
    _uri = _intent.getData();
    _imgSource.load(_uri).execute(mLoadCallback);
}

private final LoadCallback mLoadCallback = new LoadCallback() {
    @Override public void onSuccess() {
    }

    @Override public void onError(Throwable e) {
    }
};

private final CropCallback mCropCallback = new CropCallback() {
    @Override public void onSuccess(Bitmap _data) {
        _bitmap = _data;
        _cropBtn.stop();
        _imgPreview.setImageBitmap(_data);
    }

    @Override public void onError(Throwable e) {
        _fragment.showCompAlert(_popView, "Failed to create a cropped image from your image source.");
    }
};

private void showHideImages(String _str) {

    if (_cropBtn.isRotating()) {
        return;
    }
    switch (_str) {
        case Tag_ShowCrop:
            _pickBtn.setVisibility(View.VISIBLE);
            _leftBtn.setVisibility(View.VISIBLE);
            _rightBtn.setVisibility(View.VISIBLE);
            _imgPreview.setVisibility(View.GONE);
            _imgSource.setVisibility(View.VISIBLE);
            _cropBtn.setImageDrawable(_cropDraw);
            break;
        case Tag_ShowPreview:
            _pickBtn.setVisibility(View.INVISIBLE);
            _leftBtn.setVisibility(View.INVISIBLE);
            _rightBtn.setVisibility(View.INVISIBLE);
            _imgSource.setVisibility(View.GONE);
            _imgPreview.setVisibility(View.VISIBLE);
            _cropBtn.setImageDrawable(_clearDraw);
            _imgPreview.setImageDrawable(null);
            break;
        default:
            break;
    }
}

public void close(){
    _popup.dismiss();
    _fragment._compCropView = null;
}

}

@stonelai
Copy link
Author

stonelai commented Sep 3, 2017

fragmentme .java
-- from where a crop window is spawned

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == android.app.Activity.RESULT_OK) {
        switch (requestCode) {
            case AsyncRequestTypes.Local_Request_Photo:
                if (_compCropView == null) {
                    _compCropView = (compCrop) getActivity().getLayoutInflater().inflate(R.layout.comp_crop, null);
                    _compCropView.start(_fragment, data, _requestType);
                }
                else{
                    _compCropView.loadImage(data);
                }
                break;
            default:
                break;
        }
    }
}

@igreenwood
Copy link
Owner

Hi,

Thanks for your response.
Seems like not a bug in the library.
I think the cause of this bug is that CropImageView.loadAsync() is called after the view has detached from window.

・You shouldn't hold the fragment in your custom view class because the reference loops and causes the memory leaks.
・You shouldn't inflate the view multiple time in the onActivityResult() . You should inflate the view only once in onCreateView() .

Please see my sample as reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants