您的位置:首页 > 移动开发

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

2016-11-14 20:28 393 查看
先上效果图:



获取手机已安装的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能够依然保持我们代码逻辑的简洁和易懂。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android app
相关文章推荐