利用RxJava获取手机已安装的App的图片、应用名称和版本号

先上效果图:

获取手机已安装的App列表利用Android系统API就可以办到,这里为什么要引入RxJava?现在我们假设一下有下面几个需求:

1、我们不需要所有的App,只需要用户安装的第三方App,即过滤到系统App;

2、我们自定义一个AppInfo类,该类中保存了App_Icon、App_Name、App_VersionName等属性,而Android系统提供的API我们只能获取ApplicationInfo,这样就存在一个类型转换;

3、获取Application信息,过滤数据这些操作都是相对耗时的操作,我们需要在工作线程进行操作,获取数据后,我们又需要切换到UI线程进行结果的显示,这又涉及到线程的切换。

基于上面的需求,我们用传统的java代码来实现,相对来说比较麻烦,既然RxJava现在这么火,我们就利用RxJava来实现上面的几个需求。本文所涉及的RxJava操作符主要包括filter、map两个操作符。

一、定义一个AppInfo类,用来保存我们需要显示的信息

public class AppInfo {
    private Drawable appIcon;
    private String appName;
    private String appVersionName;

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }

    public String getAppVersionName() {
        return appVersionName;
    }

    public void setAppVersionName(String appVersionName) {
        this.appVersionName = appVersionName;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }
}

二、定义一个Adapter

public class AppInfoAdapter extends RecyclerView.Adapter<AppInfoAdapter.AppInfoViewHolder> {

    private List<AppInfo> mData;

    public AppInfoAdapter(List<AppInfo> data) {
        mData = data;
    }

    @Override
    public AppInfoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View rootView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_app_info, parent, false);

        return new AppInfoViewHolder(rootView);
    }

    @Override
    public void onBindViewHolder(AppInfoViewHolder holder, int position) {
        AppInfo appInfo = mData.get(position);

        if (appInfo == null) {
            return;
        }

        if (appInfo.getAppIcon() != null) {
            holder.appIcon.setImageDrawable(appInfo.getAppIcon());
        }

        if (!TextUtils.isEmpty(appInfo.getAppName())) {
            holder.appName.setText(appInfo.getAppName());
        }

        if (!TextUtils.isEmpty(appInfo.getAppVersionName())) {
            holder.appVersionCode.setText(appInfo.getAppVersionName());
        }
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }

    public class AppInfoViewHolder extends RecyclerView.ViewHolder {

        private ImageView appIcon;
        private TextView appName;
        private TextView appVersionCode;

        public AppInfoViewHolder(View itemView) {
            super(itemView);

            appIcon = (ImageView) itemView.findViewById(R.id.app_icon);
            appName = (TextView) itemView.findViewById(R.id.app_name);
            appVersionCode = (TextView) itemView.findViewById(R.id.app_version_code);
        }
    }

}

三、显示页面

显示页面主要是一个RecyclerView列表,用来展示手机中已经安装的App列表。布局什么的就不多说了,直接上代码:

 private void getAllApp() {
        Observable.create(new Observable.OnSubscribe<PackageInfo>() {
            @Override
            public void call(Subscriber<? super PackageInfo> subscriber) {
                List<PackageInfo> packageInfoList = getInstalledApp(getPackageManager());
                for (PackageInfo info : packageInfoList) {
                    subscriber.onNext(info);
                }
                subscriber.onCompleted();
            }
        })
                .map(new Func1<PackageInfo, AppInfo>() {
                    @Override
                    public AppInfo call(PackageInfo packageInfo) {
                        AppInfo appInfo = new AppInfo();
                        appInfo.setAppIcon(packageInfo.applicationInfo.loadIcon(getPackageManager()));
                        appInfo.setAppName(packageInfo.applicationInfo.loadLabel(getPackageManager()).toString());
                        appInfo.setAppVersionName(packageInfo.versionName);
                        return appInfo;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<AppInfo>() {
                    @Override
                    public void onCompleted() {
                        mAdapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError: " + e.toString());
                    }

                    @Override
                    public void onNext(AppInfo appInfo) {
                        mData.add(appInfo);
                    }
                });
    }

    private void getThirdPartyApp() {
        Observable.create(new Observable.OnSubscribe<PackageInfo>() {
            @Override
            public void call(Subscriber<? super PackageInfo> subscriber) {
                List<PackageInfo> packageInfoList = getInstalledApp(getPackageManager());
                for (PackageInfo info : packageInfoList) {
                    subscriber.onNext(info);
                }
                subscriber.onCompleted();
            }
        })
                .filter(new Func1<PackageInfo, Boolean>() {
                    @Override
                    public Boolean call(PackageInfo packageInfo) {
                      //过滤系统应用
                        return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0;
                    }
                })
                .map(new Func1<PackageInfo, AppInfo>() {
                    @Override
                    public AppInfo call(PackageInfo packageInfo) {
                        AppInfo appInfo = new AppInfo();
                        appInfo.setAppIcon(packageInfo.applicationInfo.loadIcon(getPackageManager()));
                        appInfo.setAppName(packageInfo.applicationInfo.loadLabel(getPackageManager()).toString());
                        appInfo.setAppVersionName(packageInfo.versionName);
                        return appInfo;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<AppInfo>() {
                    @Override
                    public void onCompleted() {
                        mAdapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError: " + e.toString());
                    }

                    @Override
                    public void onNext(AppInfo appInfo) {
                        mData.add(appInfo);
                    }
                });
    }

    private List<PackageInfo> getInstalledApp(PackageManager pm) {
        return pm.getInstalledPackages(0);
    }

通过getInstalledApp方法,我们可以获取到系统的安装的应用的PackageInfo,在getAllApp刚发中,通过subscriber.onNext(info)发送PackageInfo;由于PackageInfo中包含了所有的App信息,而这并不是我们需要的,我们只需要用户安装的App就可以,这样就要求过滤掉系统App,RxJava提供了一个filter操作符来进行过滤操作,通过map操作我们就可以把系统应用过滤掉;另外,我们需要将获得的PackageInfo转换为我们定义的AppInfo类型,而RxJava只需要一个map操作符就能完成转换,这样就可以把获取的App信息保存到AppInfo类中。

通过上面的过滤和变换之后,我们就可以得到AppInfo,然后在onNext方法中通过mData.add(appInfo)把结果添加进List集合中,onCompleted方法中通知Adapter进行更新mAdapter.notifyDataSetChanged()。

看似复杂的一系列需求,得益于RxJava优秀API设计,使得数据的过滤、变换等操作变得十分简单,同时RxJava的流式API设计,即使我们的逻辑很复杂的情况下,RxJava能够依然保持我们代码逻辑的简洁和易懂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值