Solution to the problem of recycle view reuse disorder
Achieving results
- Single item selection with checkBox
- After killing the application in the background, enter the application again to display the options when killing the application in the background
Problem description
- Because recyclerView adopts the reuse strategy, when refreshing the list downward, the item objects out of view will be reused on the new list, resulting in the confusion of click events.
- Check box clicking is not mutually exclusive
- Can't display the options before killing the application
Solutions
1. The recyclerview click event will reuse the confusion. However, the content displayed will not be disordered. You can know that the position will not be disordered.
2. Add a boolean field selected in our data class to record the selected status.
3. Add a click event in the recyclerView to change the selected value, and implement it correctly during initialization
4. Define the mSelectedPos field of int type in activity, which is used to record the mutually exclusive event of checkBox implemented by the position of item in the last clicked
Don't talk too much. Add code and comments
1.activity class description
public class MainActivity extends Activity {
private List<AppInfo> mAppInfoList = new ArrayList<>();
private int mSelectedPos = 0;//Define the location of the last clicked item in the field record to realize mutual exclusion
private ListAdapter mAdapter;
private RecyclerView mRecyclerView;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new ListAdapter();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter);
initData();
}
class ListAdapter extends RecyclerView.Adapter<ListAdapter.MyViewHolder> {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
MainActivity.this).inflate(R.layout.item_home, parent,
false));
return holder;
}
//Each time you scroll to add a new item, the following functions are polled and executed to initialize the item
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.textView.setText(mAppInfoList.get(position).getAppName());
holder.imageView.setImageDrawable(mAppInfoList.get(position).getIcon());
holder.checkBox.setChecked(mAppInfoList.get(position).isSelected());//Mappinfo list is the collection of objects we want to display. AppInfo objects are placed in the collection. AppInfo objects encapsulate the pictures and text information to be displayed. It is important to add a boolean type selected field.
if (mAppInfoList.get(position).isSelected()) {
mSelectedPos = position;//This if statement is used in conjunction with our initialization of the data set. It sets the selected field of the appInfo instance of the item before we exit the application to true. When we encounter an item that is true, it is the item that we select before we exit the application. Assign its position to mSelectedPos. when we click the new item, set the checkBox of the original item to false.
}
holder.checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAppInfoList.get(mSelectedPos).setSelected(false);
//setting up a new Item checkout state
mSelectedPos = position;
mAppInfoList.get(mSelectedPos).setSelected(true);
notifyDataSetChanged();
SharedPreferences.Editor editor = WidgetUtil.getEditor(MainActivity.this);//The widget util class is a tool class that encapsulates various methods and fields. This is to get the Editor object and save the packageName value
editor.putString(WidgetUtil.PACKAGE_NAME, mAppInfoList.get(position).getPackageName());
editor.putInt("radioId", position);
editor.commit();
Intent intent = new Intent();
intent.setAction(WidgetUtil.BINGING_ICON_ACTION);
sendBroadcast(intent);
}
});
}
@Override
public int getItemCount() {
return mAppInfoList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
ImageView imageView;
CheckBox checkBox;
public MyViewHolder(View view) {
super(view);
textView = (TextView) view.findViewById(R.id.id_num);
imageView = (ImageView) view.findViewById(R.id.id_image);
checkBox = (CheckBox) view.findViewById(R.id.id_check_box);
}
}
}
public ListAdapter getAdapter() {
if (mAdapter == null) {
return null;
} else {
return mAdapter;
}
}
public void initData() {
final Runnable mUpdateResults = new Runnable() {
public void run() {
mAdapter.notifyDataSetChanged();
}
};
new Thread(new Runnable() {
@Override
public void run() {
mAppInfoList = WidgetUtil.getAppsInfoList(MainActivity.this);
mHandler.post(mUpdateResults);
}
}).start();
}
}
2. Widget util source code of tool class
class WidgetUtil {
//You don't need to know the specific meaning of these fields, just focus on how we realize mutual exclusion
public static final String WIDGET_BUTTON_ACTION = "cn.byd.Widget_Button_Click";
public static final String BINGING_ICON_ACTION = "com.byd.intent.action.BINGING_ICON";
public static final String PACKAGE_ADDED_ACTION = "android.intent.action.PACKAGE_ADDED";
public static final String PACKAGE_REMOVED_ACTION = "android.intent.action.PACKAGE_REMOVED";
public static final String WIDGET_OPEN_APP_INFO = "widget_open_app_info";
public static final String PACKAGE_NAME = "packageName";
public static final String PACKAGE = "package";
public static final String WIDGET_APP_NAME = "com.android.firstapp";
//Get the package name of the system installed for all applications,
// and return to the list of all the package names
//The main purpose of this function is to obtain the information of all installed apps in the system, encapsulate the package name, application name, icon and version of the installed app into AppInfo object, and put the AppInfo object into the collection
public static List<AppInfo> getAppsInfoList(Context context) {
List<PackageInfo> packages = context.getPackageManager().getInstalledPackages(0);
List<AppInfo> allAppInfo = new ArrayList<>();
SharedPreferences share = context.getSharedPreferences(WIDGET_OPEN_APP_INFO, context.MODE_PRIVATE);
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
for (int i = 0; i < packages.size(); i++) {
AppInfo appInfo = new AppInfo();
PackageInfo packageInfo = packages.get(i);
//If non - system applications are used, add to "allAppInfo
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
appInfo.setPackageName(packageInfo.packageName);
appInfo.setAppName(packageInfo.applicationInfo.loadLabel(context.getPackageManager()).toString());
appInfo.setVersionName(packageInfo.versionName);
appInfo.setIcon(packageInfo.applicationInfo.loadIcon(context.getPackageManager()));
appInfo.setSelected(false);//Important: set the selected of all objects to false by default, that is to say, the item on the view is not selected by default.
if (share.getString(PACKAGE_NAME,"a").equals(packageInfo.packageName)){
appInfo.setSelected(true);//The key point of the entire if statement is to record the item option you clicked when you quit the application. When you restart the application, reset the item you selected before exiting to the selected state
}
allAppInfo.add(appInfo);//If non - system applications are used, add to "allAppInfo"
}
}
return allAppInfo;
}
//Getting editor
public static SharedPreferences.Editor getEditor(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences(WIDGET_OPEN_APP_INFO, context.MODE_PRIVATE);
SharedPreferences.Editor mEditor = sharedPreferences.edit();
return mEditor;
}
}
3.AppInfo class analysis
public class AppInfo implements Serializable {
private String packageName;
private String appName;
private String versionName;
private Drawable icon;
private int ID;
private boolean selected;//Pay attention to this field. There is no comment for ordinary Java beans
public int getID() {
return ID;
}
public String getPackageName() {
return packageName;
}
public String getAppName() {
return appName;
}
public String getVersionName() {
return versionName;
}
public Drawable getIcon() {
return icon;
}
public boolean isSelected() {
return selected;
}
public void setID(int ID) {
this.ID = ID;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public void setIcon(Drawable icon) {
this.icon = icon;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
The role of the whole code
The whole code is to extract all the apps installed in the mobile phone and use recyclerView to display the icon and name of the installed app, and realize single selection.