将Matisse进程化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28268507/article/details/78259926

将Matisse进程化

Matisse是什么?

Matisse是知乎团队开源的一个设计良好的本地图片/视频文件选择库,支持不同的图片加载方式。

先来张效果图,镇镇压。

1-1F42310521GC.png

具体的使用方法,参考官方Sample

github 地址: https://github.com/zhihu/Matisse

什么是多进程?为什么要多进程?

正常情况下,一个apk启动后就是一个进程,这是系统的默认行为,其进程名就是我们在AndroidManifest.xml配置的包名。多进程之间的内存是不可见的,所以这也是我们手机上运行某款app突然崩溃后,并没有影响到其他app的原因。不过我们可以使用android:process属性,来将我们的app配置成多进程。

多进程的好处:

  • 减轻app负担,将内存均匀化。什么意思呢,我们知道Android系统对每个应用进程的内存占用是有限制的,而且占用内存越大的进程,通常被系统杀死的可能性越大。而让app多进程化,可以减少主进程所占用的内存,降低被系统杀死的概率;

  • 如果子进程崩溃后,并不影响主进程,我们可以继续工作;

多进程的坏处:

  • 由于进程之间内存是不可见的,所以我们无法像平时一样正常的通讯。不过安卓已经提供了相应的跨进程之间通讯的技术,如AIDL,Messager,ContentProvider,Socket…等。这里不讨论具体的实现方案,大家可以自行百度;

微博App安卓客户端配置了5个进程:

微信图片_20171017133353.jpg

公司项目中安卓客户端进程化:

微信图片_20171017133828.png

公司项目中配置了4个:

  • com.shengda.extension 主进程
  • com.shengda.extension:mult 子进程,极光推送后台服务
  • com.shengda.extension:remote 子进程,百度地位后台服务
  • com.shengda.extension:matisse 子进程,Matisse图片选择库

为什么需要把Matisse配置成单独进程?

我们都知道图片在手机中是比较占用内存的,如果处理不好会很容易造成OOM而导致App崩溃的,所以这里对Matisse的简单修改,来达到应用的进程化;

应用多进程化的细节

当一个应用配置了多个进程后,那么Application会有多个,它和进程的数量是相对的。所以我们要注意下平时在Application所做的初始化工作。

如下:

public static Context mApplicationContext;

@Override
public void onCreate() {
    super.onCreate();
    mApplicationContext = this.getApplicationContext();
    //x5内核初始化
    //initX5();
    //极光推送初始化
    JPushInterface.init(mApplicationContext);
    //初始化百度地图
    SDKInitializer.initialize(mApplicationContext);
    this.registerActivityLifecycleCallbacks(callbacks);
    //全局异常捕获
    MobclickAgent.setCatchUncaughtExceptions(false);
    CrashHandler.getInstance().init();
}

由于我们的应用以及多进程了,所以这里的初始化并不是每一个进程都需要用到的,所以我们建议修改为如下:

public static Context mApplicationContext;

@Override
public void onCreate() {
    super.onCreate();
    mApplicationContext = this.getApplicationContext();
    //如果是主进程,则开始初始化第三方sdk,因为这些sdk只有在主进程中才被使用到
    if(AppUtils.isMainProcess(mApplicationContext)){
        //x5内核初始化
        //initX5();
        //极光推送初始化
        JPushInterface.init(mApplicationContext);
        //初始化百度地图
        SDKInitializer.initialize(mApplicationContext);
    }
    this.registerActivityLifecycleCallbacks(callbacks);
    //全局异常捕获
    MobclickAgent.setCatchUncaughtExceptions(false);
    CrashHandler.getInstance().init();
}

将Matisse进程化

由于Matisse是开源的,所以我们需要下载他的源码并导入到Android Studio中,并在其上进行简单修改即可。

微信图片_20171017135401.png

我们打开Matisse的AndroidManifest.xml修改代码如下:

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhihu.matisse">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    //android:process 注意这个属性,也就是指定该进程的名称
    <application>
        <activity android:name="com.zhihu.matisse.ui.MatisseActivity" android:process=":matisse"/>
        <activity android:name="com.zhihu.matisse.internal.ui.AlbumPreviewActivity" android:process=":matisse"/>
        <activity android:name="com.zhihu.matisse.internal.ui.SelectedPreviewActivity" android:process=":matisse"/>
    </application>
</manifest>

然后我们看下Matisse的使用:

Matisse.from(MainActivity.this)
        .choose(MimeType.allOf())
        .countable(true)
        .maxSelectable(9)
        .addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
        .gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
        .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
        .thumbnailScale(0.85f)
        .imageEngine(new GlideEngine())
        .forResult(REQUEST_CODE_CHOOSE);

链式调用,进行了一些配置设置之后进行了startActivityForResult

public void forResult(int requestCode) {
        Activity activity = mMatisse.getActivity();
        if (activity == null) {
            return;
        }

        Intent intent = new Intent(activity, MatisseActivity.class);

        Fragment fragment = mMatisse.getFragment();
        if (fragment != null) {
            fragment.startActivityForResult(intent, requestCode);
        } else {
            activity.startActivityForResult(intent, requestCode);
        }
 }

通过简单的阅读代码后,我们知道了大概的流程,所以我们只需要将那些配置参数转换为Bundle来进行intent传输,并取出最后进行设置即可。

这里说下startActivityForResult 和 onActivityResult 是支持跨进程间的,所以这里我们无需其他的进程间通讯技术。

修改后的代码:

//工具类,直接调用,跳转到图片选择界面,最后通过onActivityResult回调选中结果
public static void openPhotoSlect(Activity activity, int maxSize) {
        Bundle bundle = new Bundle();
        bundle.putInt("maxSize",maxSize);
        bundle.putBoolean("capture",false);

        Matisse.from(activity)
                .choose(MimeType.ofImage(), false)
                .forResult(Constant.INTENT_MATISSE_REQUEST,bundle);
}

SelectionSpec源码配置参数设置,进行了一些初始值的设置:

public Set<MimeType> mimeTypeSet = MimeType.ofImage();
public boolean mediaTypeExclusive;
public boolean showSingleMediaType;
@StyleRes
public int themeId = R.style.Matisse_Zhihu;
public int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
public boolean countable = true ;
public int maxSelectable = 9;
public List<Filter> filters = new ArrayList<>();
public boolean capture;
public CaptureStrategy captureStrategy = new CaptureStrategy(true, MatisseActivity.APPLICATION_CONTEXT.getPackageName() + ".fileprovider");
public int spanCount;
public int gridExpectedSize = MatisseActivity.APPLICATION_CONTEXT.getResources().getDimensionPixelSize(R.dimen.grid_expected_size);
public float thumbnailScale = 0.85f;
public ImageEngine imageEngine = new GlideEngine();

private SelectionSpec() {
    filters.add(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K));
}

这里我们就完成了Matisse的进程化,最后说下Matisse的细节问题。

由于项目中有图片预览功能和图片选择功能,所以统一使用了Matisse。如果大家没对源码进行任何修改,则直接使用图片预览功能会报错,原因就是SelectionSpec的配置没有默认值,大家可以采用以下方式解决:

一、 在使用预览功能之前对起配置进行设置

Matisse.from(MainActivity.this)
        .choose(MimeType.allOf())
        .countable(true)
        .maxSelectable(9)
        .addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
        .gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
        .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
        .thumbnailScale(0.85f)
        .imageEngine(new GlideEngine())
        //最后无需发起跳转界面,也就是forResult()无需调用

二、 SelectionSpec对这个类的源码进行配置默认值的设置

好了,Matisse进程化大概就这样了,有什么问题,请留言。

猜你喜欢

转载自blog.csdn.net/qq_28268507/article/details/78259926
今日推荐