Skip to content

Use Glide to load app icon async, to avoid loading all the icosn into… #448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions VirtualApp/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,10 @@ dependencies {
compile 'com.allenliu.versionchecklib:library:1.8.3'
compile 'com.github.medyo:android-about-page:1.2.2'
compile 'moe.feng:AlipayZeroSdk:1.1'

//Glide
implementation ('com.github.bumptech.glide:glide:4.8.0') {
exclude(group: "com.android.support")
}
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}
11 changes: 10 additions & 1 deletion VirtualApp/app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,13 @@

#导航
-keep class com.amap.api.navi.**{*;}
-keep class com.autonavi.**{*;}
-keep class com.autonavi.**{*;}

##--Glide--
-keep class com.bumptech.glide.**{*;}
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
33 changes: 33 additions & 0 deletions VirtualApp/app/src/main/java/io/virtualapp/glide/GlideUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.virtualapp.glide;

import android.content.Context;
import android.support.annotation.DrawableRes;
import android.widget.ImageView;

import com.bumptech.glide.load.engine.DiskCacheStrategy;

import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_FILE_PATH_PREFIX;
import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_PREFIX;

/**
* Created by Windy on 2018/10/25
*/
public class GlideUtils {

public static void loadInstalledPackageIcon(Context context, String packageName, ImageView target, @DrawableRes int placeHolder) {
GlideApp.with(context)
.load(DATA_PACKAGE_PREFIX + packageName)
.placeholder(placeHolder)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(target);
}

public static void loadPackageIconFromApkFile(Context context, String apkFilePath, ImageView target, @DrawableRes int placeHolder) {
GlideApp.with(context)
.load(DATA_PACKAGE_FILE_PATH_PREFIX + apkFilePath)
.placeholder(placeHolder)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(target);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.virtualapp.glide;

import android.content.Context;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.engine.cache.LruResourceCache;
import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
import com.bumptech.glide.module.AppGlideModule;
import com.lody.virtual.helper.utils.VLog;

import java.io.InputStream;

/**
* Created by Windy on 2018/10/25
*/
@GlideModule
public class MyGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
.build();
builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize() / 2));

VLog.i("MyGlideModule", "applyOptions");
}

@Override
public boolean isManifestParsingEnabled() {
return false;
}

@Override
public void registerComponents(Context context, Glide glide, Registry registry) {
super.registerComponents(context, glide, registry);
registry.prepend(String.class, InputStream.class, new PackageIconResourceLoaderFactory(context));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package io.virtualapp.glide;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;

import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.data.DataFetcher;
import com.lody.virtual.helper.utils.VLog;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_FILE_PATH_PREFIX;
import static io.virtualapp.glide.PackageIconResourceLoader.DATA_PACKAGE_PREFIX;

/**
* Created by Windy on 2018/10/25
*/
public class PackageIconResourceDataFetcher implements DataFetcher<InputStream> {

private static final String TAG = PackageIconResourceDataFetcher.class.getSimpleName();

private Context context;
private String packageModel;

private InputStream data;

public PackageIconResourceDataFetcher(Context context, String packageName) {
this.context = context.getApplicationContext();
this.packageModel = packageName;
}

@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
try {
data = loadResource();
} catch (Exception e) {
VLog.e(TAG, "Failed to load data from asset manager", e);
callback.onLoadFailed(e);
return;
}
callback.onDataReady(data);
}

@Override
public void cleanup() {
if (data == null) {
return;
}
try {
data.close();
} catch (IOException e) {
// Ignored.
}
}

@Override
public void cancel() {

}

@NonNull
@Override
public Class<InputStream> getDataClass() {
return InputStream.class;
}

@NonNull
@Override
public DataSource getDataSource() {
return DataSource.LOCAL;
}

//load icon res accord to package name, or apk path
private InputStream loadResource() {
PackageInfo packageInfo = null;
Drawable drawable = null;
try {
packageInfo = getPackageInfo();
if (packageInfo == null) {
return null;
}

drawable = packageInfo.applicationInfo.loadIcon(context.getPackageManager());
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (drawable == null) {
return null;
}
return drawableToInputStream(drawable);
}

private PackageInfo getPackageInfo() throws PackageManager.NameNotFoundException {
if (packageModel.startsWith(DATA_PACKAGE_PREFIX)) {
return context.getPackageManager().getPackageInfo(getPackageTrueModel(DATA_PACKAGE_PREFIX), 0);
} else if (packageModel.startsWith(DATA_PACKAGE_FILE_PATH_PREFIX)) {
return context.getPackageManager().getPackageArchiveInfo(getPackageTrueModel(DATA_PACKAGE_FILE_PATH_PREFIX), 0);
}
return null;
}

private String getPackageTrueModel(String prefix) {
return packageModel.replaceAll(prefix, "");
}

private InputStream drawableToInputStream(Drawable drawable) {
Bitmap bitmap = drawableToBitmap(drawable);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //use the compression format of your need
return new ByteArrayInputStream(stream.toByteArray());
}

private static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}

int width = drawable.getIntrinsicWidth();
width = width > 0 ? width : 1;
int height = drawable.getIntrinsicHeight();
height = height > 0 ? height : 1;

Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);

return bitmap;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.virtualapp.glide;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.signature.ObjectKey;

import java.io.InputStream;

/**
* Created by Windy on 2018/10/25
*/
public class PackageIconResourceLoader implements ModelLoader<String, InputStream> {

public static final String DATA_PACKAGE_PREFIX = "data:packageName/";
public static final String DATA_PACKAGE_FILE_PATH_PREFIX = "data:packageFilePath/";

private Context context;


public PackageIconResourceLoader(Context context) {
this.context = context;
}

@Nullable
@Override
public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) {
return new LoadData<>(new ObjectKey(model), new PackageIconResourceDataFetcher(context, model));
}

@Override
public boolean handles(@NonNull String model) {
return model.startsWith(DATA_PACKAGE_PREFIX) || model.startsWith(DATA_PACKAGE_FILE_PATH_PREFIX);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.virtualapp.glide;

import android.content.Context;
import android.support.annotation.NonNull;

import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import com.bumptech.glide.load.model.MultiModelLoaderFactory;

import java.io.InputStream;

/**
* Created by Windy on 2018/10/25
*/
public class PackageIconResourceLoaderFactory implements ModelLoaderFactory<String, InputStream> {

private Context context;

public PackageIconResourceLoaderFactory(Context context) {
this.context = context;
}

@NonNull
@Override
public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
return new PackageIconResourceLoader(context);
}

@Override
public void teardown() {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL);
dividerItemDecoration.setDrawable(new ColorDrawable(0x1f000000));
mRecyclerView.addItemDecoration(dividerItemDecoration);
mAdapter = new CloneAppListAdapter(getActivity());
mAdapter = new CloneAppListAdapter(getActivity(), getSelectFrom());
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new CloneAppListAdapter.ItemEventListener() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.virtualapp.home.adapters;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
Expand All @@ -9,10 +10,12 @@
import android.widget.ImageView;
import android.widget.TextView;

import java.io.File;
import java.util.List;

import io.virtualapp.R;
import io.virtualapp.abs.ui.VUiKit;
import io.virtualapp.glide.GlideUtils;
import io.virtualapp.home.models.AppInfo;
import io.virtualapp.widgets.DragSelectRecyclerViewAdapter;
import io.virtualapp.widgets.LabelView;
Expand All @@ -28,7 +31,13 @@ public class CloneAppListAdapter extends DragSelectRecyclerViewAdapter<CloneAppL
private List<AppInfo> mAppList;
private ItemEventListener mItemEventListener;

public CloneAppListAdapter(Context context) {
private Context mContext;
private File mFrom;


public CloneAppListAdapter(Context context, @Nullable File from) {
mContext = context;
mFrom = from;
this.mInflater = LayoutInflater.from(context);
mFooterView = new View(context);
StaggeredGridLayoutManager.LayoutParams params = new StaggeredGridLayoutManager.LayoutParams(
Expand Down Expand Up @@ -67,7 +76,13 @@ public void onBindViewHolder(ViewHolder holder, int position) {
}
super.onBindViewHolder(holder, position);
AppInfo info = mAppList.get(position);
holder.iconView.setImageDrawable(info.icon);

if (mFrom == null) {
GlideUtils.loadInstalledPackageIcon(mContext, info.packageName, holder.iconView, android.R.drawable.sym_def_app_icon);
} else {
GlideUtils.loadPackageIconFromApkFile(mContext, info.path, holder.iconView, android.R.drawable.sym_def_app_icon);
}

holder.nameView.setText(String.format("%s: %s", info.name, info.version));
if (isIndexSelected(position)) {
holder.iconView.setAlpha(1f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ private List<AppInfo> convertPackageInfoToAppData(Context context, List<PackageI
info.packageName = pkg.packageName;
info.fastOpen = fastOpen;
info.path = path;
info.icon = ai.loadIcon(pm);
// info.icon = ai.loadIcon(pm);
info.icon = null; // Use Glide to load the icon async
info.name = ai.loadLabel(pm);
info.version = pkg.versionName;
InstalledAppInfo installedAppInfo = VirtualCore.get().getInstalledAppInfo(pkg.packageName, 0);
Expand Down
Loading