2015-11-21 77 views
1

我已經編寫了顯示已安裝應用程序列表以及複選框的代碼。但是,當我關閉應用程序時,複選框值會重置。我瞭解到,通過使用共享首選項,我可以保存複選框的狀態。但是我無法在我的項目中實現它。我對此很新。所以,我要求提供詳細的解決方案。此外,我還有一個問題。在此代碼中,複選框的狀態保存在名爲checklist的數組中。相反,可以創建名稱與應用程序名稱相同的布爾變量(我們從PackageManager中獲得),值將爲複選框的狀態。例如 布爾瀏覽器或布爾相機。該代碼發佈如下。提前致謝!!如何將customedapter中的ArrayList保存到SharedPreference

MainActivity.java

public class MainActivity extends ListActivity { 
    private PackageManager packageManager = null; 
    private List<ApplicationInfo> applist = null; 
    private ApplicationAdapter listadapter = null; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     packageManager = getPackageManager(); 

     new LoadApplications().execute(); 
    } 

    @Override 
    protected void onListItemClick(ListView l, View v, int position, long id) { 
     super.onListItemClick(l, v, position, id); 

     ApplicationInfo app = applist.get(position); 
     try { 
      Intent intent = packageManager 
        .getLaunchIntentForPackage(app.packageName); 

      if (null != intent) { 
       startActivity(intent); 
      } 
     } catch (ActivityNotFoundException e) { 
      Toast.makeText(MainActivity.this, e.getMessage(), 
        Toast.LENGTH_LONG).show(); 
     } catch (Exception e) { 
      Toast.makeText(MainActivity.this, e.getMessage(), 
        Toast.LENGTH_LONG).show(); 
     } 
    } 

    private List<ApplicationInfo> checkForLaunchIntent(List<ApplicationInfo> list) { 
     ArrayList<ApplicationInfo> applist = new ArrayList<ApplicationInfo>(); 
     for (ApplicationInfo info : list) { 
      try { 
       if (null != packageManager.getLaunchIntentForPackage(info.packageName)) { 
        applist.add(info); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     return applist; 
    } 

    private class LoadApplications extends AsyncTask<Void, Void, Void> { 
     private ProgressDialog progress = null; 

     @Override 
     protected Void doInBackground(Void... params) { 
      applist = checkForLaunchIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA)); 
      listadapter = new ApplicationAdapter(MainActivity.this, 
        R.layout.row, applist); 

      return null; 
     } 

     @Override 
     protected void onCancelled() { 
      super.onCancelled(); 
     } 

     @Override 
     protected void onPostExecute(Void result) { 
      setListAdapter(listadapter); 
      progress.dismiss(); 
      super.onPostExecute(result); 
     } 

     @Override 
     protected void onPreExecute() { 
      progress = ProgressDialog.show(MainActivity.this, null, 
        "Loading application info..."); 
      super.onPreExecute(); 
     } 

     @Override 
     protected void onProgressUpdate(Void... values) { 
      super.onProgressUpdate(values); 
     } 
    } 
} 

ApplicationAdapter.java

public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> { 
    private List<ApplicationInfo> appsList = null; 
    private Context context; 
    private PackageManager packageManager; 
    private ArrayList<Boolean> checkList = new ArrayList<Boolean>(); 

    public ApplicationAdapter(Context context, int textViewResourceId, 
           List<ApplicationInfo> appsList) { 
     super(context, textViewResourceId, appsList); 
     this.context = context; 
     this.appsList = appsList; 
     packageManager = context.getPackageManager(); 

     for (int i = 0; i < appsList.size(); i++) { 
      checkList.add(false); 
     } 
    } 

    @Override 
    public int getCount() { 
     return ((null != appsList) ? appsList.size() : 0); 
    } 

    @Override 
    public ApplicationInfo getItem(int position) { 
     return ((null != appsList) ? appsList.get(position) : null); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view = convertView; 
     if (null == view) { 
      LayoutInflater layoutInflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = layoutInflater.inflate(R.layout.row, null); 
     } 

     ApplicationInfo data = appsList.get(position); 
     if (null != data) { 
      TextView appName = (TextView) view.findViewById(R.id.app_name); 
      TextView packageName = (TextView) view.findViewById(R.id.app_package); 
      ImageView iconview = (ImageView) view.findViewById(R.id.app_icon); 

      CheckBox checkBox = (CheckBox) view.findViewById(R.id.cb_app); 
      checkBox.setTag(Integer.valueOf(position)); // set the tag so we can identify the correct row in the listener 
      checkBox.setChecked(checkList.get(position)); // set the status as we stored it 
      checkBox.setOnCheckedChangeListener(mListener); // set the listener 

      appName.setText(data.loadLabel(packageManager)); 
      packageName.setText(data.packageName); 
      iconview.setImageDrawable(data.loadIcon(packageManager)); 
     } 
     return view; 
    } 
    CompoundButton.OnCheckedChangeListener mListener = new CompoundButton.OnCheckedChangeListener() { 

     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
      checkList.set((Integer)buttonView.getTag(),isChecked); // get the tag so we know the row and store the status 
     } 
    }; 
} 

activity_main.xml中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <ListView 
     android:id="@android:id/list" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content"> 

    </ListView> 

</LinearLayout> 

row.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal"> 

    <ImageView 
     android:id="@+id/app_icon" 
     android:layout_width="50dp" 
     android:layout_height="50dp" 
     android:scaleType="centerCrop" 
     android:padding="3dp" 
     android:src="@drawable/download" /> 

    <LinearLayout 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:gravity="center_vertical" 
     android:orientation="vertical" 
     android:paddingLeft="5dp" > 

     <TextView 
      android:id="@+id/app_name" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:gravity="center_vertical" 
      android:textStyle="bold" /> 

     <TextView 
      android:id="@+id/app_package" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:gravity="center_vertical" /> 
    </LinearLayout> 


    <CheckBox 
     android:id="@+id/cb_app" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

</LinearLayout> 

編輯: 根據@Falco Winkler的建議,我修改了我的自定義適配器,如下所示。

ApplicationAdapter.java

import android.content.Context; 
import android.content.SharedPreferences; 
import android.content.pm.ApplicationInfo; 
import android.content.pm.PackageManager; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.CheckBox; 
import android.widget.CompoundButton; 
import android.widget.ImageView; 
import android.widget.TextView; 

import java.util.ArrayList; 
import java.util.List;  

public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> { 
    private List<ApplicationInfo> appsList = null; 
    private Context context; 
    private PackageManager packageManager; 
    private SharedPreferences prefs; 
    public ApplicationAdapter(Context context, int textViewResourceId, 
           List<ApplicationInfo> appsList) { 
     super(context, textViewResourceId, appsList); 
     this.context = context; 
     this.appsList = appsList; 
     packageManager = context.getPackageManager(); 
     prefs = context.getSharedPreferences("checkboxstate",Context.MODE_PRIVATE); 
    } 



    @Override 
    public int getCount() { 
     return ((null != appsList) ? appsList.size() : 0); 
    } 

    @Override 
    public ApplicationInfo getItem(int position) { 
     return ((null != appsList) ? appsList.get(position) : null); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view = convertView; 
     if (null == view) { 
      LayoutInflater layoutInflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = layoutInflater.inflate(R.layout.row, null); 
     } 

     ApplicationInfo data = appsList.get(position); 
     if (null != data) { 
      TextView appName = (TextView) view.findViewById(R.id.app_name); 
      TextView packageName = (TextView) view.findViewById(R.id.app_package); 
      ImageView iconview = (ImageView) view.findViewById(R.id.app_icon); 

      CheckBox checkBox = (CheckBox) view.findViewById(R.id.cb_app); 
      checkBox.setTag(String.valueOf(appName)); // set the tag so we can identify the correct row in the listener 
      checkBox.setChecked(prefs.getBoolean(checkBox.getTag().toString(), false)); // set the status as we stored it 

      checkBox.setOnClickListener(onclicklistener); 
      appName.setText(data.loadLabel(packageManager)); 
      packageName.setText(data.packageName); 
      iconview.setImageDrawable(data.loadIcon(packageManager)); 
     } 
     return view; 
} 

    CheckBox.OnClickListener onclicklistener = new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 

      prefs.edit().putBoolean(v.getTag().toString(),((CheckBox)v).isChecked()).apply(); 

     } 
    }; 
} 

然而,複選框的值仍然沒有保存和重置一切後,我關閉應用程序。我錯過了什麼?

EDIT1: 根據新的建議,我修改了我的自定義適配器。但是,即使我看到一些複選框已經被選中,它也是隨機的。例如,如果我檢查第三個複選框並重新打開應用程序,第二個複選框將被選中而不是第三個。此外,還有一些其他複選框是隨機選擇的。我在下面發佈修改後的代碼。

package com.example.monika.savenotification; 

import android.content.Context; 
import android.content.SharedPreferences; 
import android.content.pm.ApplicationInfo; 
import android.content.pm.PackageManager; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.CheckBox; 
import android.widget.CompoundButton; 
import android.widget.ImageView; 
import android.widget.TextView; 

import java.util.ArrayList; 
import java.util.List; 

public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo> { 
    private List<ApplicationInfo> appsList = null; 
    private Context context; 
    private PackageManager packageManager; 
    public ApplicationAdapter(Context context, int textViewResourceId, 
           List<ApplicationInfo> appsList) { 
     super(context, textViewResourceId, appsList); 
     this.context = context; 
     this.appsList = appsList; 
     packageManager = context.getPackageManager(); 


    } 



    @Override 
    public int getCount() { 
     return ((null != appsList) ? appsList.size() : 0); 
    } 

    @Override 
    public ApplicationInfo getItem(int position) { 
     return ((null != appsList) ? appsList.get(position) : null); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view = convertView; 
     if (null == view) { 
      LayoutInflater layoutInflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = layoutInflater.inflate(R.layout.row, null); 
     } 

     final ApplicationInfo data = appsList.get(position); 
     final SharedPreferences prefs = context.getSharedPreferences("checkboxstate", Context.MODE_PRIVATE); 
     if (null != data) { 
      TextView appName = (TextView) view.findViewById(R.id.app_name); 
      TextView packageName = (TextView) view.findViewById(R.id.app_package); 
      ImageView iconview = (ImageView) view.findViewById(R.id.app_icon); 

      CheckBox checkBox = (CheckBox) view.findViewById(R.id.cb_app); 
      checkBox.setTag(data); // set the tag so we can identify the correct row in the listener 


      checkBox.setChecked(prefs.getBoolean(data.packageName, false)); // set the status as we stored it 


      checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
       @Override 
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
        prefs.edit().putBoolean(data.packageName, isChecked).apply(); 

       } 
      }); 

      appName.setText(data.loadLabel(packageManager)); 
      packageName.setText(data.packageName); 
      iconview.setImageDrawable(data.loadIcon(packageManager)); 
     } 
     return view; 
} 


} 

需要做哪些修改?在此先感謝..

+0

SharedPreferences的聯機文檔非常簡單。你爲什麼不能實現它?你有沒有試過,如果有的話,你有什麼問題? –

回答

2

使用共享首選項,可以使用字符串作爲鍵,以及布爾或任何其他基元數據類型作爲值。

因此,在您onClickListener你可以這樣做:

SharedPreferences prefs = activity.getSharedPreferences(
        "com.company.yourapp", Context.MODE_PRIVATE); 

prefs.edit().putBoolean(buttonView.getTag().toString, isChecked).apply(); 

如果你想確定一個複選框的狀態只是做:

prefs.getBoolean(yourTag.toString(), false); 

雖然false是默認值你當這個標籤還沒有被保存過(例如複選框沒有被選中)

另外我會建議你設置你的複選框的事件監聽器像這樣:

checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
      if (isChecked) { 
       ApplicationInfo info = appsList.get(position); 

      } 
     } 
    }); 

在獲取視圖的方法,這樣你就可以直接訪問您的數據源(ApplicationInfo列表)。請注意,您必須將位置參數聲明爲final。

編輯

你的問題,現在似乎是這一行:

checkBox.setTag(String.valueOf(appName)); 

雖然應用程序名稱是您的TextView的標識符。您的複選框的標籤將因此被設置爲textView的字符串表示形式,這是一些調試信息。你可能的意思是:

checkBox.setTag(data); 

我想你想辦法很複雜。只需在獲取視圖中嘗試以下操作:

final ApplicationInfo data = appsList.get(position); 
    ... 
    final SharedPreferences prefs = activity.getSharedPreferences(
      "com.company.yourapp", Context.MODE_PRIVATE); 

    checkBox.setChecked(prefs.getBoolean(data.packageName, false)); 
    checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 

      prefs.edit().putBoolean(data.packageName, isChecked).apply(); 
     } 
    }); 
+0

嗨。 @Falco Winker,謝謝你的回覆。我根據您的建議修改了代碼。我仍然面臨問題。請查看編輯部分 – Anonymous

+0

好的,看看我的編輯。我指出了一個明顯的錯誤。我還發布了一個(未經測試的)代碼,該代碼現在應該適用於您。 –

+0

現在我看到一些複選框已經被選中。然而,它是隨機的。例如,如果我檢查第三個複選框,重新打開應用程序後,第二個複選框將被選中。另外,其他一些複選框是隨機選擇的。 – Anonymous

相關問題