上一篇TakePhoto框架源码流程解析(一)地址,这一篇打算详细介绍下TakePhotoImpl的使用,毕竟是TakePhoto的核心类,所有的调用都会回调到这个类中,所以还是有必要学习下,对自己的编程能力还是有很大提升的。
在上一篇介绍到,当我们调用接口的某个方法时,都会走动态代理的TakePhotoInvocationHandler
的invoke
方法,最后会回调到TakePhotoImpl
的对应方法。 接下来继续看下下面几个常用方法的流程。
onPickMultiple
从相册选择多张图片,这个相册是自定义的一个相册,而不是系统相册,我们可以限制选择的图片数量,看下其实现:
@Override
public void onPickMultiple(int limit) {
if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return;
TUtils.startActivityForResult(contextWrap, new TIntentWap(IntentUtils.getPickMultipleIntent(contextWrap, limit), TConstant.RC_PICK_MULTIPLE));
}
首先判断TPermissionType
的状态是否为TPermissionType.WAIT
,表示在等待用户同意权限,如果在等待,就不会执行接下来的方法,否则接下来继续往下执行。下面一段封装了跳转页面的Intent
实现,TIntentWap
封装了一个Intent
和requestCode
,而Intent
是由IntentUtils.getPickMultipleIntent
获取的,看下实现
/**
* 获取图片多选的Intent
* @param limit 最多选择图片张数的限制
* */
public static Intent getPickMultipleIntent(TContextWrap contextWrap, int limit){
Intent intent = new Intent(contextWrap.getActivity(), AlbumSelectActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_LIMIT, limit>0? limit:1);
return intent;
}
可以知道选择图片的Activity
为AlbumSelectActivity
,图片限制可以通过Constants.INTENT_EXTRA_LIMIT
添加。图片选择完之后通过onActivityResult
回调,通过requestCode
可知道执行的对应的代码位置为:
.....
case TConstant.RC_PICK_MULTIPLE://多选图片返回结果
if (resultCode == Activity.RESULT_OK && data != null) {
ArrayList<Image> images = data.getParcelableArrayListExtra(Constants.INTENT_EXTRA_IMAGES);
if (cropOptions != null) {
try {
onCrop(MultipleCrop.of(TUtils.convertImageToUri(contextWrap.getActivity(), images), contextWrap.getActivity(), fromType), cropOptions);
} catch (TException e) {
cropContinue(false);
e.printStackTrace();
}
} else {
takeResult(TResult.of(TUtils.getTImagesWithImages(images, fromType)));
}
} else {
listener.takeCancel();
}
break;
通过判断是否配置cropOptions
,来决定是否裁剪图片,否则执行takeResult
。
private void takeResult(final TResult result, final String... message) {
if (null == compressConfig) {
handleTakeCallBack(result, message);
} else {
if (showCompressDialog)
wailLoadDialog = TUtils.showProgressDialog(contextWrap.getActivity(), contextWrap.getActivity().getResources().getString(R.string.tip_compress));
....................................
}
}
在takeResult
中,通过判断是否压缩图片,来决定走那个回调,先来判断不压缩图片,压缩的部分后面单独讲。不压缩部分走handleTakeCallBack(result, message);
方法
private void handleTakeCallBack(final TResult result, String... message) {
if (message.length > 0) {
listener.takeFail(result, message[0]);
} else if (multipleCrop != null && multipleCrop.hasFailed) {
listener.takeFail(result, contextWrap.getActivity().getResources().getString(R.string.msg_crop_failed));
} else if (compressConfig != null) {
boolean hasFailed = false;
for (TImage image : result.getImages()) {
if (image == null || !image.isCompressed()) {
hasFailed = true;
break;
}
}
if (hasFailed) {
listener.takeFail(result, contextWrap.getActivity().getString(R.string.msg_compress_failed));
} else {
listener.takeSuccess(result);
}
} else {
listener.takeSuccess(result);
}
clearParams();
}
这个方法是去处理图片的结果,如果配置了multipleCrop
和compressConfig
,就去判断是否有裁剪失败
或者有没有压缩的图片
如果都不满足,才去执行listener.takeSuccess(result);
方法,也就是我们在业务逻辑处理的takeSuccess
方法。处理完之后会调用clearParams()
清除配置的压缩
,裁剪
,拍照
属性,所以我们下次调用之前要重新配置这些属性。onPickMultiple
的流程介绍就这多了。
onPickMultipleWithCrop
它比onPickMultiple
多了个裁剪功能,看下其裁剪实现
onCrop(MultipleCrop.of(TUtils.convertImageToUri(contextWrap.getActivity(), images), contextWrap.getActivity(), fromType), cropOptions);
裁剪会走这个流程,封装了一个MultipleCrop
和cropOptions
,TUtils.convertImageToUri
里面兼容到7.0了。而onCrop
可以通过配置,来使用自己的或者第三方的裁剪。
onPickFromDocuments, onPickFromGallery
这两个方法都是选择相片,一个是从文档,一个是从相册获取,两个方法都会走selectPicture
,看下实现
private void selectPicture(int defaultIndex, boolean isCrop) {
this.fromType = TImage.FromType.OTHER;
if (takePhotoOptions != null && takePhotoOptions.isWithOwnGallery()) {
onPickMultiple(1);
return;
}
if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return;
ArrayList<TIntentWap> intentWapList = new ArrayList<>();
intentWapList.add(new TIntentWap(IntentUtils.getPickIntentWithDocuments(), isCrop ? TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_CROP : TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL));
intentWapList.add(new TIntentWap(IntentUtils.getPickIntentWithGallery(), isCrop ? TConstant.RC_PICK_PICTURE_FROM_GALLERY_CROP : TConstant.RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL));
try {
TUtils.sendIntentBySafely(contextWrap, intentWapList, defaultIndex, isCrop);
} catch (TException e) {
takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage());
e.printStackTrace();
}
}
如果我们是用自己的相册,就直接走onPickMultiple
方法,否则在一个List
里面封装两个intent
,然后结合defaultIndex
,来决定使用那个intent
,intent
里面封装了选择相片的方式。
onPickFromGalleryWithCrop, onPickFromDocumentsWithCrop
上面两个方法的扩展,可以在选择完图片之后,再去裁剪图片。
onPickFromCapture, onPickFromCaptureWithCrop
这两个方法为去拍照和拍照并裁剪。这两个方法都会去将传进来的url
适配到7.0。
if (Build.VERSION.SDK_INT >= 23) {
this.tempUri = TUriParse.getTempUri(contextWrap.getActivity());
} else {
this.tempUri = outPutUri;
}
然后调用TUtils.captureBySafely
,来打开系统相机。最后调用onCrop
裁剪相片。
最后
基本的使用就是这多了,接下来将会介绍下TakePhoto
的压缩实现。