如何在Custom BaseAdapter中有效地存储复选框值

时间:2014-08-15 20:02:41

标签: java android sqlite android-listview sharedpreferences

过去两周,当我退出并打开应用程序时,我一直在努力制作一个解决方案,以便在我的每个listview项目旁边存储我的复选框值。基本上,我有一个自定义的BaseAdapter类,它使用用户手机上已安装的应用程序填充列表视图,并在每个已安装的应用程序旁边打开一个复选框。当我向下滚动复选框时,状态保持不变;但是,当我单击后退或退出并返回时它不会停留。

enter image description here

我几乎以各种可能的方式使用了SharedPreferences。我的最后一种方法是使用for循环为每个创建一个SharedPreference,并在for循环中恢复布尔值,并在if和else语句中存储布尔值true和false(分别用于checked和unchecked)。

以下是使用SharedPreferences的我的BaseAdapter类的代码:

package com.ibc.android.demo.appslist.app;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.TextView;

import com.spicycurryman.getdisciplined10.app.R;

import java.util.List;

//

public class ApkAdapter extends BaseAdapter {

    //Pastebin link:  http://pastebin.com/LGRicg4U , http://pastebin.com/c4WfmhMK , http://pastebin.com/gFuuM4dY, http://pastebin.com/4Q7EP9G4
    // http://pastebin.com/Te2g072w,  http://pastebin.com/NLT5iUiA ,

    SharedPreferences sharedPrefs;
    List<PackageInfo> packageList;
    Activity context;
    PackageManager packageManager;
    boolean[] itemChecked;

    String PACKAGE_NAME;

    public ApkAdapter(Activity context, List<PackageInfo> packageList,
                      PackageManager packageManager) {
        super();
        this.context = context;
        this.packageList = packageList;
        this.packageManager = packageManager;
        itemChecked = new boolean[packageList.size()];

    }


    private class ViewHolder {
        TextView apkName;
        CheckBox ck1;
        TextView packageName;
    }

    public int getCount() {
        return packageList.size();
    }

    public Object getItem(int position) {
        return packageList.get(position);
    }

    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;

        LayoutInflater inflater = context.getLayoutInflater();

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.installed_apps, null);
            holder = new ViewHolder();

            holder.apkName = (TextView) convertView
                    .findViewById(R.id.appname);
            holder.ck1= (CheckBox)convertView
                    .findViewById(R.id.checkBox1);



            convertView.setTag(holder);
            //holder.ck1.setTag(packageList.get(position));

        } else {

            holder = (ViewHolder) convertView.getTag();
        }



        // ViewHolder holder = (ViewHolder) convertView.getTag();
        PackageInfo packageInfo = (PackageInfo) getItem(position);



        Drawable appIcon = packageManager
                .getApplicationIcon(packageInfo.applicationInfo);



        // Make sure to define it again!
        PACKAGE_NAME = packageInfo.packageName;


        final String appName = packageManager.getApplicationLabel(
                packageInfo.applicationInfo).toString();
        appIcon.setBounds(0, 0, 80, 80);
        holder.apkName.setCompoundDrawables(appIcon, null, null, null);
        holder.apkName.setCompoundDrawablePadding(15);
        holder.apkName.setText(appName);


        holder.ck1.setChecked(false);


        if (itemChecked[position])
            holder.ck1.setChecked(true);
        else
            holder.ck1.setChecked(false);

        Log.d("just loaded??", PACKAGE_NAME);


        Log.d("just loaded 2?", appName+position);



        // CHANGE UP EVERYTHING! MAKE THIS SHIT WORK, TIGGA!


        for(int i= 0; i<packageList.size(); i++){
            sharedPrefs = context.getSharedPreferences(String.valueOf(i), Context.MODE_PRIVATE);
            holder.ck1.setChecked(sharedPrefs.getBoolean(String.valueOf(i),false));


        }

        holder.ck1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {


                SharedPreferences.Editor editor = context.getSharedPreferences(String.valueOf(position), Context.MODE_PRIVATE).edit();

                if (holder.ck1.isChecked()) {
                    itemChecked[position] = true;
                    holder.ck1.setChecked(true);
                    Log.i("This is", " checked: " + position);
                    editor.putBoolean(String.valueOf(position), true);
                    Log.d("put true", appName+position);

                    editor.apply();

                } else {
                    itemChecked[position] = false;
                    holder.ck1.setChecked(false);
                    Log.i("This is", " not checked: " + position);
                    editor.putBoolean(String.valueOf(position), false);
                    Log.d("put false", appName+position);

                    editor.apply();

                }

            }


        });

        return convertView;

    }




}

我还创建了一个DatabaseHandler类和Object类,用于在使用SharedPreferences将其存储失败后使用SQLite数据库存储我的复选框值。

以下是pastebin链接,所以我不会堵塞帖子:

DatabaseHandler类:http://pastebin.com/NzKhBiZ3

对象类:http://pastebin.com/Jp3BLXba

我知道有许多关于使用自定义适配器/列表视图以及使用SQLite和SharedPreferences保存复选框和按钮状态等的帖子,博客和链接,但我向您保证,我已经完成了数周的研究,但是我我们找不到适用于我特定情况的东西。

一些例子:

Saving State of the checkbox in a custom list view with Checkboxes

http://blog.csdn.net/qu213/article/details/9289349

在我的特定情况下,什么是最优选的选项?如何在我的情况下生成一个解决方案,以成功保存每个已安装的app listview项旁边的复选框状态,这些状态将在我退出应用程序后保存重新输入?有些代码真的很有帮助。

感谢您的时间。

如果您需要我包含任何xml文件,请告诉我。

3 个答案:

答案 0 :(得分:1)

我建议您使用的是定义一个处理存储和检索状态数据的对象。假设您有一个AppHandler类作为主要对象和AppState类 用于保存状态相关数据,例如复选框。

public class AppHandler {

    private List<AppState> lastInstalledApp;
    @transient
    private Gson            gson;


    public void retrieve(SharedPreferences pref){

        // parse the gson from shared preferences
        // create the lastInstalledApp list
        String jsonState = pref.getString("APP_STATE", null);
        if(jsonState != null)
           lastInstalledApp = gson.fromJson(jsonState, lastInstalledApp.getClass());
    }

    public void store(SharedPreferences pref){

        // store the data to shared preferences
    }


    public List<AppState> getAppList(){

        return lastInstalledApp;
    }

    public static class AppState{

        protected boolean lastCheckbox;
        protected String name;
        public boolean isLastCheckbox() {
            return lastCheckbox;
        }
        public void setLastCheckbox(boolean lastCheckbox) {
            this.lastCheckbox = lastCheckbox;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }


    }

使用共享首选项将整个AppHandler对象存储为JSON字符串(为此使用GSON),因此您只能访问一次存储文件,而不是每次只想访问一个复选框状态。您可以在活动中检索并存储此数据(适配器使用您的appHandler.getAppList()数据启动它):

@Override
protected void onCreate(Bundle arg0) {
    super.onCreate(arg0);
    setContentView(R.layout.list_layout);

    appHandler = new AppHandler();
    appHandler.retrieve(getSharedPreferences());
}

@Override
protected void onDestroy() {

    appHandler.store(getSharedPreferences());
    super.onDestroy();
}
您的自定义适配器中的

通过其包名访问特定应用程序,以获取复选框的状态。您甚至可以扩展ArrayList并添加一些方法,例如getAppByName(),这样您就可以清楚地区分对象。
更改复选框状态时,更新AppState对象的等效布尔值。这是一般性的。

答案 1 :(得分:1)

我想我可能已经解决了你的问题。请尝试使用此代码,看看它是否有效。

 for(int i= 0; i<packageList.size(); i++){
            PACKAGE_NAME = packageInfo.packageName;

            sharedPrefs = context.getSharedPreferences(PACKAGE_NAME, Context.MODE_PRIVATE);
            Log.d("just got sharedpref??", PACKAGE_NAME);


            holder.ck1.setChecked(sharedPrefs.getBoolean(PACKAGE_NAME,false));
            Log.d("just got boolean??", PACKAGE_NAME);


        }

        holder.ck1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {


                SharedPreferences.Editor editor = context.getSharedPreferences(packageInfo.packageName, Context.MODE_PRIVATE).edit();

                if (holder.ck1.isChecked()) {
                    itemChecked[position] = true;
                    holder.ck1.setChecked(true);
                    Log.i("This is", " checked: " + position);
                    editor.putBoolean(packageInfo.packageName, true);
                    Log.d("put true", packageInfo.packageName);

                    editor.apply();

                } else {
                    itemChecked[position] = false;
                    holder.ck1.setChecked(false);
                    Log.i("This is", " not checked: " + position);
                    editor.putBoolean(packageInfo.packageName, false);
                    Log.d("put false", packageInfo.packageName);

                    editor.apply();

                }

            }


        });

我传入了密钥的包名。 :)

答案 2 :(得分:0)

使用sqlite数据库...每次用户检查/取消选中该值时,都会在数据库中创建一个条目。

  

检查了App1

     

检查App2

     

检查App3

     

App4取消选中