Skip to content

Commit f1bb865

Browse files
authored
Merge pull request #448 from WindySha/exposed
Use Glide to load app icon async, to avoid loading all the icosn into…
2 parents 30a6510 + 52e4636 commit f1bb865

12 files changed

+337
-18
lines changed

VirtualApp/app/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,10 @@ dependencies {
9494
compile 'com.allenliu.versionchecklib:library:1.8.3'
9595
compile 'com.github.medyo:android-about-page:1.2.2'
9696
compile 'moe.feng:AlipayZeroSdk:1.1'
97+
98+
//Glide
99+
implementation ('com.github.bumptech.glide:glide:4.8.0') {
100+
exclude(group: "com.android.support")
101+
}
102+
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
97103
}

VirtualApp/app/proguard-rules.pro

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,13 @@
3333

3434
#导航
3535
-keep class com.amap.api.navi.**{*;}
36-
-keep class com.autonavi.**{*;}
36+
-keep class com.autonavi.**{*;}
37+
38+
##--Glide--
39+
-keep class com.bumptech.glide.**{*;}
40+
-keep public class * implements com.bumptech.glide.module.GlideModule
41+
-keep public class * extends com.bumptech.glide.module.AppGlideModule
42+
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
43+
**[] $VALUES;
44+
public *;
45+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.virtualapp.glide;
2+
3+
import android.content.Context;
4+
import android.support.annotation.DrawableRes;
5+
import android.widget.ImageView;
6+
7+
import com.bumptech.glide.load.engine.DiskCacheStrategy;
8+
9+
import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_FILE_PATH_PREFIX;
10+
import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_PREFIX;
11+
12+
/**
13+
* Created by Windy on 2018/10/25
14+
*/
15+
public class GlideUtils {
16+
17+
public static void loadInstalledPackageIcon(Context context, String packageName, ImageView target, @DrawableRes int placeHolder) {
18+
GlideApp.with(context)
19+
.load(DATA_PACKAGE_PREFIX + packageName)
20+
.placeholder(placeHolder)
21+
.diskCacheStrategy(DiskCacheStrategy.NONE)
22+
.into(target);
23+
}
24+
25+
public static void loadPackageIconFromApkFile(Context context, String apkFilePath, ImageView target, @DrawableRes int placeHolder) {
26+
GlideApp.with(context)
27+
.load(DATA_PACKAGE_FILE_PATH_PREFIX + apkFilePath)
28+
.placeholder(placeHolder)
29+
.diskCacheStrategy(DiskCacheStrategy.NONE)
30+
.into(target);
31+
}
32+
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package io.virtualapp.glide;
2+
3+
import android.content.Context;
4+
5+
import com.bumptech.glide.Glide;
6+
import com.bumptech.glide.GlideBuilder;
7+
import com.bumptech.glide.Registry;
8+
import com.bumptech.glide.annotation.GlideModule;
9+
import com.bumptech.glide.load.engine.cache.LruResourceCache;
10+
import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
11+
import com.bumptech.glide.module.AppGlideModule;
12+
import com.lody.virtual.helper.utils.VLog;
13+
14+
import java.io.InputStream;
15+
16+
/**
17+
* Created by Windy on 2018/10/25
18+
*/
19+
@GlideModule
20+
public class MyGlideModule extends AppGlideModule {
21+
@Override
22+
public void applyOptions(Context context, GlideBuilder builder) {
23+
MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
24+
.build();
25+
builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize() / 2));
26+
27+
VLog.i("MyGlideModule", "applyOptions");
28+
}
29+
30+
@Override
31+
public boolean isManifestParsingEnabled() {
32+
return false;
33+
}
34+
35+
@Override
36+
public void registerComponents(Context context, Glide glide, Registry registry) {
37+
super.registerComponents(context, glide, registry);
38+
registry.prepend(String.class, InputStream.class, new PackageIconResourceLoaderFactory(context));
39+
}
40+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package io.virtualapp.glide;
2+
3+
import android.content.Context;
4+
import android.content.pm.PackageInfo;
5+
import android.content.pm.PackageManager;
6+
import android.graphics.Bitmap;
7+
import android.graphics.Canvas;
8+
import android.graphics.drawable.BitmapDrawable;
9+
import android.graphics.drawable.Drawable;
10+
import android.support.annotation.NonNull;
11+
12+
import com.bumptech.glide.Priority;
13+
import com.bumptech.glide.load.DataSource;
14+
import com.bumptech.glide.load.data.DataFetcher;
15+
import com.lody.virtual.helper.utils.VLog;
16+
17+
import java.io.ByteArrayInputStream;
18+
import java.io.ByteArrayOutputStream;
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
22+
import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_FILE_PATH_PREFIX;
23+
import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_PREFIX;
24+
25+
/**
26+
* Created by Windy on 2018/10/25
27+
*/
28+
public class PackageIconResourceDataFetcher implements DataFetcher<InputStream> {
29+
30+
private static final String TAG = PackageIconResourceDataFetcher.class.getSimpleName();
31+
32+
private Context context;
33+
private String packageModel;
34+
35+
private InputStream data;
36+
37+
public PackageIconResourceDataFetcher(Context context, String packageName) {
38+
this.context = context.getApplicationContext();
39+
this.packageModel = packageName;
40+
}
41+
42+
@Override
43+
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
44+
try {
45+
data = loadResource();
46+
} catch (Exception e) {
47+
VLog.e(TAG, "Failed to load data from asset manager", e);
48+
callback.onLoadFailed(e);
49+
return;
50+
}
51+
callback.onDataReady(data);
52+
}
53+
54+
@Override
55+
public void cleanup() {
56+
if (data == null) {
57+
return;
58+
}
59+
try {
60+
data.close();
61+
} catch (IOException e) {
62+
// Ignored.
63+
}
64+
}
65+
66+
@Override
67+
public void cancel() {
68+
69+
}
70+
71+
@NonNull
72+
@Override
73+
public Class<InputStream> getDataClass() {
74+
return InputStream.class;
75+
}
76+
77+
@NonNull
78+
@Override
79+
public DataSource getDataSource() {
80+
return DataSource.LOCAL;
81+
}
82+
83+
//load icon res accord to package name, or apk path
84+
private InputStream loadResource() {
85+
PackageInfo packageInfo = null;
86+
Drawable drawable = null;
87+
try {
88+
packageInfo = getPackageInfo();
89+
if (packageInfo == null) {
90+
return null;
91+
}
92+
93+
drawable = packageInfo.applicationInfo.loadIcon(context.getPackageManager());
94+
} catch (PackageManager.NameNotFoundException e) {
95+
e.printStackTrace();
96+
}
97+
if (drawable == null) {
98+
return null;
99+
}
100+
return drawableToInputStream(drawable);
101+
}
102+
103+
private PackageInfo getPackageInfo() throws PackageManager.NameNotFoundException {
104+
if (packageModel.startsWith(DATA_PACKAGE_PREFIX)) {
105+
return context.getPackageManager().getPackageInfo(getPackageTrueModel(DATA_PACKAGE_PREFIX), 0);
106+
} else if (packageModel.startsWith(DATA_PACKAGE_FILE_PATH_PREFIX)) {
107+
return context.getPackageManager().getPackageArchiveInfo(getPackageTrueModel(DATA_PACKAGE_FILE_PATH_PREFIX), 0);
108+
}
109+
return null;
110+
}
111+
112+
private String getPackageTrueModel(String prefix) {
113+
return packageModel.replaceAll(prefix, "");
114+
}
115+
116+
private InputStream drawableToInputStream(Drawable drawable) {
117+
Bitmap bitmap = drawableToBitmap(drawable);
118+
ByteArrayOutputStream stream = new ByteArrayOutputStream();
119+
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //use the compression format of your need
120+
return new ByteArrayInputStream(stream.toByteArray());
121+
}
122+
123+
private static Bitmap drawableToBitmap(Drawable drawable) {
124+
if (drawable instanceof BitmapDrawable) {
125+
return ((BitmapDrawable) drawable).getBitmap();
126+
}
127+
128+
int width = drawable.getIntrinsicWidth();
129+
width = width > 0 ? width : 1;
130+
int height = drawable.getIntrinsicHeight();
131+
height = height > 0 ? height : 1;
132+
133+
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
134+
Canvas canvas = new Canvas(bitmap);
135+
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
136+
drawable.draw(canvas);
137+
138+
return bitmap;
139+
}
140+
141+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.virtualapp.glide;
2+
3+
import android.content.Context;
4+
import android.support.annotation.NonNull;
5+
import android.support.annotation.Nullable;
6+
7+
import com.bumptech.glide.load.Options;
8+
import com.bumptech.glide.load.model.ModelLoader;
9+
import com.bumptech.glide.signature.ObjectKey;
10+
11+
import java.io.InputStream;
12+
13+
/**
14+
* Created by Windy on 2018/10/25
15+
*/
16+
public class PackageIconResourceLoader implements ModelLoader<String, InputStream> {
17+
18+
public static final String DATA_PACKAGE_PREFIX = "data:packageName/";
19+
public static final String DATA_PACKAGE_FILE_PATH_PREFIX = "data:packageFilePath/";
20+
21+
private Context context;
22+
23+
24+
public PackageIconResourceLoader(Context context) {
25+
this.context = context;
26+
}
27+
28+
@Nullable
29+
@Override
30+
public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) {
31+
return new LoadData<>(new ObjectKey(model), new PackageIconResourceDataFetcher(context, model));
32+
}
33+
34+
@Override
35+
public boolean handles(@NonNull String model) {
36+
return model.startsWith(DATA_PACKAGE_PREFIX) || model.startsWith(DATA_PACKAGE_FILE_PATH_PREFIX);
37+
}
38+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.virtualapp.glide;
2+
3+
import android.content.Context;
4+
import android.support.annotation.NonNull;
5+
6+
import com.bumptech.glide.load.model.ModelLoader;
7+
import com.bumptech.glide.load.model.ModelLoaderFactory;
8+
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
9+
10+
import java.io.InputStream;
11+
12+
/**
13+
* Created by Windy on 2018/10/25
14+
*/
15+
public class PackageIconResourceLoaderFactory implements ModelLoaderFactory<String, InputStream> {
16+
17+
private Context context;
18+
19+
public PackageIconResourceLoaderFactory(Context context) {
20+
this.context = context;
21+
}
22+
23+
@NonNull
24+
@Override
25+
public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
26+
return new PackageIconResourceLoader(context);
27+
}
28+
29+
@Override
30+
public void teardown() {
31+
32+
}
33+
}

VirtualApp/app/src/main/java/io/virtualapp/home/ListAppFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
162162
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
163163
dividerItemDecoration.setDrawable(new ColorDrawable(0x1f000000));
164164
mRecyclerView.addItemDecoration(dividerItemDecoration);
165-
mAdapter = new CloneAppListAdapter(getActivity());
165+
mAdapter = new CloneAppListAdapter(getActivity(), getSelectFrom());
166166
mRecyclerView.setAdapter(mAdapter);
167167
mAdapter.setOnItemClickListener(new CloneAppListAdapter.ItemEventListener() {
168168
@Override

VirtualApp/app/src/main/java/io/virtualapp/home/adapters/CloneAppListAdapter.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.virtualapp.home.adapters;
22

33
import android.content.Context;
4+
import android.support.annotation.Nullable;
45
import android.support.v7.widget.RecyclerView;
56
import android.support.v7.widget.StaggeredGridLayoutManager;
67
import android.view.LayoutInflater;
@@ -9,10 +10,12 @@
910
import android.widget.ImageView;
1011
import android.widget.TextView;
1112

13+
import java.io.File;
1214
import java.util.List;
1315

1416
import io.virtualapp.R;
1517
import io.virtualapp.abs.ui.VUiKit;
18+
import io.virtualapp.glide.GlideUtils;
1619
import io.virtualapp.home.models.AppInfo;
1720
import io.virtualapp.widgets.DragSelectRecyclerViewAdapter;
1821
import io.virtualapp.widgets.LabelView;
@@ -28,7 +31,13 @@ public class CloneAppListAdapter extends DragSelectRecyclerViewAdapter<CloneAppL
2831
private List<AppInfo> mAppList;
2932
private ItemEventListener mItemEventListener;
3033

31-
public CloneAppListAdapter(Context context) {
34+
private Context mContext;
35+
private File mFrom;
36+
37+
38+
public CloneAppListAdapter(Context context, @Nullable File from) {
39+
mContext = context;
40+
mFrom = from;
3241
this.mInflater = LayoutInflater.from(context);
3342
mFooterView = new View(context);
3443
StaggeredGridLayoutManager.LayoutParams params = new StaggeredGridLayoutManager.LayoutParams(
@@ -67,7 +76,13 @@ public void onBindViewHolder(ViewHolder holder, int position) {
6776
}
6877
super.onBindViewHolder(holder, position);
6978
AppInfo info = mAppList.get(position);
70-
holder.iconView.setImageDrawable(info.icon);
79+
80+
if (mFrom == null) {
81+
GlideUtils.loadInstalledPackageIcon(mContext, info.packageName, holder.iconView, android.R.drawable.sym_def_app_icon);
82+
} else {
83+
GlideUtils.loadPackageIconFromApkFile(mContext, info.path, holder.iconView, android.R.drawable.sym_def_app_icon);
84+
}
85+
7186
holder.nameView.setText(String.format("%s: %s", info.name, info.version));
7287
if (isIndexSelected(position)) {
7388
holder.iconView.setAlpha(1f);

VirtualApp/app/src/main/java/io/virtualapp/home/repo/AppRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ private List<AppInfo> convertPackageInfoToAppData(Context context, List<PackageI
182182
info.packageName = pkg.packageName;
183183
info.fastOpen = fastOpen;
184184
info.path = path;
185-
info.icon = ai.loadIcon(pm);
185+
// info.icon = ai.loadIcon(pm);
186+
info.icon = null; // Use Glide to load the icon async
186187
info.name = ai.loadLabel(pm);
187188
info.version = pkg.versionName;
188189
InstalledAppInfo installedAppInfo = VirtualCore.get().getInstalledAppInfo(pkg.packageName, 0);

0 commit comments

Comments
 (0)