【问题标题】:Android ListView refreshAndroid ListView 刷新
【发布时间】:2013-02-12 00:51:31
【问题描述】:

我有一个Listview,它从 sqlite 数据库中提取和显示数据。 DB 第一列中的数据显示在ListView 中,单击时,Activity 开始显示与第一列关联的列的其余部分。编辑数据时,ListView 需要更新以反映这一点,但除非重新启动应用程序,否则它不会显示更新。

我尝试在我的onResume() 方法中调用notifyDataSetChanged()startActivityForResult(),但这没有用。我应该使用什么方法来完成更新当前代码中的ListView

我知道SimpleCursorAdapter 可能会被使用,我尝试实现该代码但没有成功。我是新手,需要实际的代码来理解需要做什么。

public class LoginList extends Activity implements OnClickListener, OnItemClickListener {
    private ListView loginList;
    private Button webLogin;

    private ListAdapter loginListAdapter;

    private ArrayList<LoginDetails> loginArrayList;

    @Override 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.login_listview);
        loginList = (ListView)
        findViewById(R.id.loginlist);
        loginList.setOnItemClickListener(this);

        webLogin = (Button)
        findViewById(R.id.button3);
        webLogin.setOnClickListener(this);

        loginArrayList = new ArrayList<LoginDetails>();
        loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
        loginList.setAdapter(loginListAdapter);
    }

    @Override
    public void onClick (View v) {
        Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
        startActivity(webLoginIntent);
    }

    public List<String> populateList () {
        List<String> webNameList = new ArrayList<String>();

        dataStore openHelperClass = new dataStore (this);

        SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();

        Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);

        startManagingCursor(cursor);

        while (cursor.moveToNext()) {
            String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
            String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
            String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
            String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
            String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));

            LoginDetails lpDetails = new LoginDetails();

            lpDetails.setsName(sName);
            lpDetails.setwUrl(wUrl);
            lpDetails.setuName(uName);
            lpDetails.setpWord(pWord);
            lpDetails.setlNotes(lNotes);

            loginArrayList.add(lpDetails);
            webNameList.add(sName);
        }

        sqliteDatabase.close();
        return webNameList;
    }


    @Override
    protected void onResume() {
        super.onResume();

        loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
        loginList.setAdapter(loginListAdapter);  

    }


@Override
    public void onItemClick(AdapterView<?> arg0 , View arg1, int arg2, long arg3) {
        Toast.makeText(getApplicationContext(), "Selected ID :" + arg2, Toast.LENGTH_SHORT).show();

        Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
        LoginDetails clickedObject = loginArrayList.get(arg2);

        Bundle loginBundle = new Bundle();
        loginBundle.putString("clickedWebSite",clickedObject.getsName());
        loginBundle.putString("clickedWebAddress",clickedObject.getwUrl());
        loginBundle.putString("clickedUserName",clickedObject.getuName());
        loginBundle.putString("clickedPassWord",clickedObject.getpWord());
        loginBundle.putString("clickedNotes",clickedObject.getlNotes());

        updateDeleteLoginInfo.putExtras(loginBundle);

        startActivityForResult(updateDeleteLoginInfo, 0);   
    }
}

【问题讨论】:

  • 你试过SimpleCursorAdapter而不是ArrayAdapter吗?
  • 嗯,onResume 中的代码不可能有误,这意味着您没有在UpdateDeleteLoginList 中正确编辑数据库。当然,您可能应该使用游标适配器来确保正确性和性能;不过,我认为仍然是一个选择问题。

标签: android android-listview simplecursoradapter onresume notifydatasetchanged


【解决方案1】:

这正是Loader 的优势所在。我建议您创建一个SimpleCursorAdapter 将数据库绑定到 UI(在这种情况下为ListView),一个ContentProvider 与数据库交互,以及一个CursorLoader 来监视数据库的更改,并更新 UI必要时。 Loader 将处理所有数据库更改并通过简单地更新您的适配器来更新您的ListView。前期工作似乎很多,但一旦配置完成,功能就非常强大,并且会在整个 Android 生命周期中发挥作用。

这些教程应该会有所帮助:

【讨论】:

    【解决方案2】:

    编辑

    private ArrayList<LoginDetails> loginArrayList = new ArrayList<LoginDetails>();;
    
    @Override 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.login_listview);
        loginList = (ListView)
        findViewById(R.id.loginlist);
        loginList.setOnItemClickListener(this);
    
        webLogin = (Button)
        findViewById(R.id.button3);
        webLogin.setOnClickListener(this);
    
    
        loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,loginArrayList );
        loginList.setAdapter(loginListAdapter);
        populateList();
    }
    
    @Override
    public void onClick (View v) {
        Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
        startActivity(webLoginIntent);
    }
    
    public void populateList () {
        loginListAdapter.clear();
        loginArrayList.clear();
        dataStore openHelperClass = new dataStore (this);
    
        SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
    
        Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
    
        startManagingCursor(cursor);
    
        while (cursor.moveToNext()) {
            String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
            String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
            String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
            String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
            String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
    
            LoginDetails lpDetails = new LoginDetails();
    
            lpDetails.setsName(sName);
            lpDetails.setwUrl(wUrl);
            lpDetails.setuName(uName);
            lpDetails.setpWord(pWord);
            lpDetails.setlNotes(lNotes);
    
            loginArrayList.add(lpDetails);
            webNameList.add(sName);
        }
        loginListAdapter.notifyDatasetChanged();
        sqliteDatabase.close();
    }
    

    您正在失去对列表视图的引用,说明您的列表没有更新的原因...

    在您的代码中进行此修改。 1. 声明时初始化 ArrayList(全局)。

    ArrayList loginArrayList = new ArrayList<LoginDetails>();
    
    1. 直接给Adapter设置assign list(onCreate)

      loginListAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, loginArrayList);

    2. onCreate() 中调用populateList()

    3. 在您的 populateList() 中,而不是将数据添加到新列表中,而是添加到与您的适配器关联的现有列表中,即 loginArrayList

    如果您的列表是全新的,请在将数据添加到 loginArrayList 之前,在 populateList() 中调用 adapter.clear()loginArrayList.clear()。 将数据添加到loginArrayList 后调用adapter.notifyDataSetChanged()

    这应该可以工作...

    【讨论】:

    • 你能提供第2步和第3步的例子吗
    • 我在您的代码中做了一些更改,请参阅...我已经在我的数据库中尝试了相同的代码并且运行良好
    • adapter.notifyDataSetChanged() 上的小语法说明:如果您找不到适配器,请考虑 ((BaseAdapter) getListView().getAdapter()).notifyDataSetChanged()
    【解决方案3】:

    我的建议。

    1. 不要循环加载您的列表。如果它是一个包含所有内容的简单列表 字符串。尝试使用SimpleCursorAdapter 并制作您的应用程序 更快更短的代码。
    2. 更新数据库后,您要做的就是查询数据库以获取Cursor,并使用.swapCursor(newCursor) 获取Adapter。这将在保持滚动位置的同时更新您的列表。

    【讨论】:

      【解决方案4】:

      如果您手动创建适配器的支持数据(在这种情况下,您使用的是 ArrayAdapter - 这在很多情况下是完全可以接受的),那么当数据库更改时,您需要重新查询数据库,重新创建您的数据集,更改适配器的支持数据集,并告诉列表数据集已更改。

      实现此目的的一种方法可能是广播一个意图,让您的 Activity 知道执行上述步骤(通过使用 BroadcastReceiver 捕获该意图)。

      【讨论】:

      • 听起来合乎逻辑。有没有提到这个过程的任何例子。这将非常有帮助。
      【解决方案5】:

      这是我的示例代码,用于编辑每一行以及列表视图的数据库,希望对您有所帮助

      首先创建我创建一个适配器名称“ListAdapterItem.java”

           import java.util.ArrayList;
           import java.util.HashMap;
      
           import android.content.Context;
           import android.view.LayoutInflater;
           import android.view.View;
           import android.view.ViewGroup;
           import android.widget.BaseAdapter;
           import android.widget.RelativeLayout;
           import android.widget.TextView;
      
           public class ListAdapterItem extends BaseAdapter {
      
      private ArrayList<HashMap<String, Object>> list;
      private Context context;
      private RelativeLayout ll;
      // used to keep selected position in ListView
      private int selectedPos = -1; // init value for not-selected
      private TextView label,label_id;
      String name,id;
      
      public ListAdapterItem (Context context,ArrayList<HashMap<String, Object>> list) {
          this.list = list;
          this.context = context;
      }
      public void setSelectedPosition(int pos) {
          selectedPos = pos;
          // inform the view of this change
          notifyDataSetChanged();
      }
      public int getSelectedPosition() {
          return selectedPos;
      }
      public View getView(int position, View convertView, ViewGroup parent) {
          ll = (RelativeLayout) LayoutInflater.from(this.context).inflate(R.layout.data_list_item, null);
          // get text view
          label = (TextView) ll.findViewById(R.id.txtview_country_name);
          label_id=(TextView) ll.findViewById(R.id.txtview_id);
      
          id=list.get(position).get("Id").toString();
          name = list.get(position).get("Name").toString();
      
          label.setText(name);
          label_id.setText(id);
          return ll;
      }
      public int getCount() {
          return this.list.size();
      }
      public Object getItem(int position) {
          return position;
      }
      public long getItemId(int position) {
          return position;
      }
      }
      

      这是我的 data_list_item

                                  <?xml version="1.0" encoding="utf-8"?>
                  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                      android:layout_width="match_parent"
                      android:layout_height="fill_parent"
                      android:orientation="vertical"
                      android:padding="5dp">
                       <TextView
                          android:id="@+id/txtview_id"
                          android:layout_width="wrap_content"
                          android:layout_height="fill_parent"
                          android:layout_margin="8dp"
                          android:layout_marginRight="2dp"
                          android:textColor="@android:color/black"
                          android:textSize="22dp"
                          android:visibility="invisible"/>
                      <TextView
                          android:id="@+id/txtview_country_name"
                          android:layout_width="wrap_content"
                          android:layout_height="fill_parent"
                          android:layout_margin="8dp"
                          android:layout_marginRight="2dp"
                          android:textColor="@android:color/black"
                          android:textSize="22dp" />
      
      
                  </RelativeLayout>
      

      还有主类“Main.java”

                          public class Main extends Activity implements OnClickListener {
      
                          String name;
                          SQLiteDatabase db;
                          Cursor cursor;
      
                          private ProgressDialog progressDialog;
      
                          public ListAdapterItem list_adapter;
                          private ArrayList<HashMap<String, Object>> lst_data;
                          private HashMap<String, Object> hm;
                          private ListView listview;
                          private String list_id;
                          private int counter_id,selectedPosition;
                          private View selectedView;
      
                          public void onCreate(Bundle savedInstanceState) {
                              super.onCreate(savedInstanceState);
                              setContentView(R.layout.main_layout);
                              lst_data = new ArrayList<HashMap<String, Object>>();
                              listview = (ListView) findViewById(R.id.list);
                              new FetchDB().execute();
                              }
                          private class FetchDB extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
                              protected void onPreExecute() {
                                  progressDialog = ProgressDialog.show(Main.this,"Fetching Data", "Loading,Please wait...", true);
                              }
      
                              protected ArrayList<HashMap<String, Object>> doInBackground(String... lstStrings)throws IllegalArgumentException {
                                  try {
                                      db = openOrCreateDatabase("MyDB", MODE_PRIVATE, null);
                                      cursor = db.rawQuery("SELECT * FROM person WHERE Id <> ''",null);
      
                                      if (cursor != null && cursor.getCount() > 0) {
      
                                          if (cursor.moveToFirst()) {
                                              do {
                                                  hm = new HashMap<String, Object>();
                                                  hm.put("Id",cursor.getInt(cursor.getColumnIndex("Id")));
                                                  hm.put("Name", cursor.getString(cursor.getColumnIndex("Name")));
                                                  lst_data.add(hm);
      
                                              } while (cursor.moveToNext());
                                          }// end of cursor.moveToFirst()
                                          cursor.close();
                                      }
      
                                  } catch (Exception e) {
                                      e.getMessage();
                                  }
                                  db.close();// database close
                                  return lst_data;
                              }// end of doInbackgournd
      
                              @Override
                              protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
                                  progressDialog.dismiss();
                                  list_adapter = new ListAdapterItem(Main.this,result);
                                  listview.setAdapter(list_adapter);
                                  listview.setOnItemClickListener(new OnItemClickListener() {
      
                                      public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
                                          list_adapter.setSelectedPosition(arg2);
                                          selectedPosition = arg2;
                                          selectedView = arg1;
                                          list_id=((TextView) selectedView.findViewById(R.id.txtview_id)).getText().toString();
                                      }
      
                                  });
                              }
                          }// end of FetchDBTask
                              private class SaveTask extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
                              @Override
                              protected void onPreExecute() {
                                  progressDialog = ProgressDialog.show(Main.this,"Saving Data", "Loading,Please wait...", true);
                              }
                              protected ArrayList<HashMap<String, Object>> doInBackground(String... arg0)throws IllegalArgumentException {
                                  counter_id++;
                                  name = editext_name.getText().toString();
      
                                  hm = new HashMap<String, Object>();
                                  hm.put("Id",counter_id);
                                  hm.put("Name",name);
                                  lst_data.add(hm);
                                  saveDB();
                                  return lst_data;
                              }// end of doInbackgournd
      
                              protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
                                  progressDialog.dismiss();
                                  list_adapter = new ListAdapterItem(Main.this,result);
                                  listview.setAdapter(list_adapter);
                                  listview.setOnItemClickListener(new OnItemClickListener() {
                                      public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
                                          list_adapter.setSelectedPosition(arg2);
                                          selectedPosition = arg2;
                                          selectedView = arg1;
                                          list_id=((TextView) selectedView.findViewById(R.id.txtview_id)).getText().toString();
      
                                      }
                                  });
      
                              }
      
                          }// end of saveTask
                          public void saveDB(){
                              String sql;
                              db = openOrCreateDatabase("MyDB", MODE_PRIVATE, null);
                              // create table if not e exist
                              db.execSQL("CREATE TABLE IF NOT EXISTS person(Name VARCHAR ,Id INT(3));");
                              sql = "SELECT * FROM person WHERE Id="+list_id; //selected or click row in list item
                              Cursor cursor = db.rawQuery(sql, null);
      
                              if (cursor.moveToFirst()) {
                                  String sqlUpdate = "UPDATE person SET Name=? WHERE Id="+db_id;
                                  db.execSQL(sqlUpdate, new Object[] {db_name});
                                  cursor.close();
                                  db.close();// database close
                              } else {// empty insert
                                  String sqlInsert = "INSERT INTO person VALUES (?,"+null+")";
                                  db.execSQL(sqlInsert, new Object[] {db_name,db_address,db_phone,db_email,db_license,db_comments,db_company,db_policy,db_phone_insurance,vehc_year,vehc_make,vehc_model,vehc_license,vehc_vinnum,vehc_color,db_position });
                                  cursor.close();
                                  db.close();// database close
      
                              }
                          }
                          //Edit by row
                          private class EditData extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
                              protected void onPreExecute() {
                                  progressDialog = ProgressDialog.show(Main.this,"Saving Data", "Loading Please wait...", true);
                              }
                              protected ArrayList<HashMap<String, Object>> doInBackground(String... id)throws IllegalArgumentException {
                                  name = editext_name.getText().toString();
      
      
                                  hm = new HashMap<String, Object>();
                                  hm.put("Id",counter_id);
                                  hm.put("Name",name);
      
                                  lst_data.set(selectedPosition, hm); //specific row update
                                  list_id=Integer.parseInt(edit_counter);
                                  saveDB();
      
                                  return lst_data;
                              }// end of doInbackgournd
                              protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
                                  progressDialog.dismiss();
                                  list_adapter = new ListAdapterItem(Main.this,result);
                                  listview.setAdapter(list_adapter);
      
                              }
                          }
                      }
      

      还有main_layout.xml

                  <?xml version="1.0" encoding="utf-8"?>
                  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"                    
                      android:orientation="vertical" >
      
                      <ListView
                          android:id="@+id/list"
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:layout_gravity="center_vertical"
                          android:background="@android:color/transparent"
                          android:cacheColorHint="#00000000"
                          android:dividerHeight="2dp"
                          android:paddingTop="8dp"
                          android:transcriptMode="normal" />
      
                  </LinearLayout>
      

      在列表视图中的每个列表行中指定您的 ID,希望这能回答您的问题

      【讨论】:

      • 我目前可以编辑我的数据。我的问题是在我的编辑完成后刷新我的列表视图,而无需关闭并重新启动应用程序。
      • 你的意思是所有的行?还是您单击并编辑的每一行?.. 对我来说,我正在使用 hashmap 自动替换 UI 视图中的每个条目
      【解决方案6】:

      我认为在 while 块之前的 populate() 方法中,您应该调用 loginListAdapter.notifyDataSetChanged() 和 loginListAdapter.clear(); 这将清除适配器并通知它新的数据列表。

      该块将如下所示:

       loginListAdapter.notifyDataSetChanged();
       loginListAdapter.clear();
       while (cursor.moveToNext()) {
              String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
              String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
              String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
              String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
              String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
      
              LoginDetails lpDetails = new LoginDetails();
      
              lpDetails.setsName(sName);
              lpDetails.setwUrl(wUrl);
              lpDetails.setuName(uName);
              lpDetails.setpWord(pWord);
              lpDetails.setlNotes(lNotes);
      
              loginArrayList.add(lpDetails);
              webNameList.add(sName);
          }
      

      我刚刚进行了编辑,因为您调用 notify 和 clear 的顺序不正确。清除必须在通知之后发生,这正是我从我的经验中得到的,除非适配器不会重绘列表。

      【讨论】:

      • 添加您推荐的更改后,我收到以下错误:
      • ListAdapter 类型的 notifyDataSetChanged() 方法未定义,ListAdapter 类型的 clear() 方法未定义
      • 你的 ListAdapter 看起来像吗: public class ListAdapter extends ArrayAdapter> {
      【解决方案7】:

      试试这个代码

      在公共区域添加变量:List&lt;String&gt; arrayList = new ArrayList&lt;String&gt;();

      并在 onCreate() 中添加:

          arrayList = populateList();
      

      //然后像这样在适配器中添加变量

      loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList );
      

      在 onResume() 中这段代码:

      @Override
      protected void onResume() {
          super.onResume();
      
          loginArrayList.clear();
      
          arrayList.clear();
      
          arrayList = populateList();
      
          loginListAdapter.notifyDataSetChanged()
      
      }
      

      如果你解决了,请告诉我们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-18
        • 2011-01-08
        • 2016-01-17
        • 2016-04-22
        相关资源
        最近更新 更多