【问题标题】:Refresh ListView (with BaseAdapter) after SQLiteDatabase data changedSQLiteDatabase 数据更改后刷新 ListView(使用 BaseAdapter)
【发布时间】:2014-04-07 19:40:40
【问题描述】:

首先,我想为提出这个问题道歉,因为我知道这里有很多类似的问题,但没有一个答案能解决我的问题。

正如问题的标题所示,当 SQLiteDatabase 中的数据发生变化时,我需要用新项目填充 ListView。

更具体一点...

我有一个在 ListView 中显示联系人的活动。在屏幕底部我有一个添加联系人的按钮(会弹出一个对话框,其中包含姓名、电话号码等字段......)。

当单击列表中的项目时,会打开另一个对话框。在该对话框中,有 3 个按钮用于发送短信(发送至所选联系人)、编辑和删除联系人。

当我填写添加新联系人的表单,或单击删除按钮时,我希望刷新 ListView。

这不会发生。为了查看更新后的列表,我需要返回并再次启动联系人活动。

代码如下:

活动:

public class ContactsActivity extends Activity {


private MyUtilities myUtilities;
private MyDatabaseHelper mdbh;
private AdapterContactListView contactsAdapter;
private ListView contactsListView;  

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_contacts);
    mdbh = new MyDatabaseHelper(this);
    myUtilities = new MyUtilities(this);    
    contactsAdapter = new AdapterContactListView(this,mdbh);
    contactsListView = (ListView)findViewById(R.id.contactActivityLV);
    contactsListView.setAdapter(contactsAdapter);

    contactsAdapter.notifyDataSetChanged();

    contactsListView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // TODO Auto-generated method stub
            TextView phoneNumberTV = (TextView)view.findViewById(R.id.contactElementNumberTV);              
            String phoneNumber = phoneNumberTV.getText().toString();
            Contact contact = mdbh.getContactFromPhoneNumber(phoneNumber);              
            Dialog d = myUtilities.createSelectedContactOptionsDialog(contact);
            d.show();
            contactsAdapter.updateAdapter(mdbh.getAllContacts());               
        }
    });


public void addContact(View view) {
        Dialog d = myUtilities.createAddContactDialog();
        d.show();
        contactsAdapter.updateAdapter(mdbh.getAllContacts());
    }
}

Adater:

private List<Contact> allContacts;
private int numberOfContacts;
private MyDatabaseHelper mdbh;
private Context context;

public AdapterContactListView(Context c, MyDatabaseHelper m) {
    super();
    context = c;
    mdbh = m;
    allContacts = mdbh.getAllContacts();
    numberOfContacts = allContacts.size();
}

public void updateAdapter(List<Contact> cs) {
    allContacts = cs;
    numberOfContacts = allContacts.size();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    View view = convertView;
    if (view == null) {
        LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = li.inflate(R.layout.contact_element, null);
    }
    String fullName = allContacts.get(position).getFirstName();
    fullName = fullName.concat(" ");
    fullName = fullName.concat(allContacts.get(position).getLastName());

    TextView contactName = (TextView)view.findViewById(R.id.contactElementNameTV);
    TextView phoneNumber = (TextView)view.findViewById(R.id.contactElementNumberTV);

    contactName.setText(fullName);
    phoneNumber.setText(allContacts.get(position).getPhoneNumber());

    return view;
}

对话框的工作是对数据库进行操作(更新、添加、删除)。

我尝试将notifyDataSetChanged() 放在updateAdapter() 之后和updateAdapter() 方法本身中,但这些都不起作用。

我想我可能会遗漏一件事:

notifyDataSetChanged() 的定义表示它通知附加的观察者。我没有附加观察员,但在我读过的所有答案中,没有人提到任何关于附加观察员的事情。如果您认为这是问题所在,请告诉我该怎么做。

有人可以解释一下这个问题吗?

提前致谢。

【问题讨论】:

  • 不,不,不,不要使用 BaseAdapter,改用 SimpleCursorAdapter
  • 很抱歉我的无知,但我尝试的一切都失败了。我的适配器现在扩展了 CursorAdapter。 ListView 填充良好,但问题仍然存在。当我关闭对话框时,列表不会刷新。我仍然需要关闭活动并重新启动它才能看到正确的列表。我在关闭对话框后尝试调用adapter.changeCursoradapter.notifyDataSetChanged(因为对话框处理数据库操作)。我尝试在onResume 中调用它...但没有。请帮忙!我被困住了。

标签: android listview android-listview baseadapter


【解决方案1】:

要刷新您的列表视图,您可以从名为 notifydatasetchanged 的​​列表中调用一个方法,但这仅在您获得联系人列表中的联系人时才有效。所以你需要做的是你应该首先在你的arraylist中获取新数据,然后在你的listview上调用notifydataset changed。

除此之外,如果您使用的是联系人数据库,我建议您使用简单的光标适配器而不是基本适配器,但这完全取决于您。无论如何,我也为此添加了代码。如果对您有帮助,请告诉我。

    /**
     * 
     * @author Syed Ahmed Hussain
     */
    public class TestListActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor>, MultiChoiceModeListener {

    NotificationsAdapter mNotificationAdapter;

    ListView mNotificationsListView;
    TextView mTxtNotificationsInfo;
    Button mBtnCreateNotification;

    public static final String TAG = "NotificationsList";


    // ---------------------------------------------------------------------------

    @Override
    protected void onCreate(Bundle pSavedInstanceState) {
        super.onCreate(pSavedInstanceState);
        setContentView(R.layout.fragment_notifications);
        initializeUIElements();
//      registerForContextMenu(mNotificationsListView);
        getSupportLoaderManager().initLoader(0, null, this);
        mNotificationsListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        mNotificationsListView.setMultiChoiceModeListener(this);
    }

    // ---------------------------------------------------------------------------

    /**
     * 
     */
    private void initializeUIElements() {
        mTxtNotificationsInfo   = (TextView) findViewById(R.id.txtNotificationInfo);
        mNotificationsListView  = (ListView) findViewById(R.id.list_notifications);
        mBtnCreateNotification  = (Button) findViewById(R.id.btnAddNotification);
    }

    // ---------------------------------------------------------------------------

    /**
     * 
     */
    public void onCreateNewNotificationClick(View pV) {
        Log.d(TAG, "onCreateNewNotificationClick");
        Intent intent = new Intent(this, AddNewNotification.class);
        startActivity(intent);
//      setResult(0);
//      finish();
    }

    // ---------------------------------------------------------------------------

    @Override
    public Loader<Cursor> onCreateLoader(int pId, Bundle pArgs) {
        return new android.support.v4.content.CursorLoader(getApplicationContext(), NotificationsContentProvider.CONTENT_URI, null, null, null, null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> pLoader, Cursor pData) {
        if (pData == null || pData.getCount() == 0) {
            Log.d("pData", "is null");
            showTextView();
            return;
        }
        mNotificationAdapter = new NotificationsAdapter(this, R.layout.item_notification, pData, new String[] { NotificationDatabaseHelper.COL_TITLE }, new int[] {R.id.txtNotificationTitle}, 0);
        mNotificationsListView.setAdapter(mNotificationAdapter);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> pLoader) {

    }

    // ---------------------------------------------------------------------------

    /**
     * Hides the list view. shows the textview
     */
    private void showTextView() {
        mNotificationsListView.setVisibility(View.GONE);
        mTxtNotificationsInfo.setVisibility(View.VISIBLE);
    }


    // ---------------------------------------------------------------------
    // Multi-choice list item

    @Override
    public boolean onCreateActionMode(ActionMode pMode, Menu pMenu) {
         // Inflate the menu for the CAB
        MenuInflater inflater = pMode.getMenuInflater();
        inflater.inflate(R.menu.menu_list_item, pMenu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode pMode, Menu pMenu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode pMode, MenuItem pItem) {

        switch (pItem.getItemId()) {
        case 1:
            Toast.makeText(getApplicationContext(), pItem.getTitle(), Toast.LENGTH_SHORT).show();
            pMode.finish();
            break;

        case 2:
            Toast.makeText(getApplicationContext(), pItem.getTitle(), Toast.LENGTH_SHORT).show();
            pMode.finish();
            break;

        default:
            break;
        }

        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode pMode) {

    }

    @Override
    public void onItemCheckedStateChanged(ActionMode pMode, int pPosition, long pId, boolean pChecked) {

    }

    // --------------------------------------------------------------------

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu items for use in the action bar
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.actionbar_menu_items, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }



}

**

  • 通知适配器是一个简单的光标适配器:

**

/**
 *  
 * @author Syed Ahmed Hussain
 */
public class NotificationsAdapter extends SimpleCursorAdapter {


    private LayoutInflater mLayoutInflater;
    private Context mContext;
    private int mLayout;

    public NotificationsAdapter(Context pContext, int pLayout, Cursor pC, String[] pFrom, int[] pTo, int pFlags) {
        super(pContext, pLayout, pC, pFrom, pTo, pFlags);
        mLayout             = pLayout;
        mContext            = pContext;
        mLayoutInflater     = LayoutInflater.from(mContext);


    }

    @Override
    public View newView(Context pContext, Cursor pCursor, ViewGroup pParent) {
        return mLayoutInflater.inflate(mLayout, null);
    }

}

要在记录发生更改时更新它,请执行 notifydatasetchange 或使用刷新游标来获取所有值。回想一下返回数据集/光标的方法。

【讨论】:

  • 谢谢 Ahmed 和 pskink。我还没有解决我的问题,但你的回答让我更深入地挖掘。我在这里发现:link 使用 'CursorAdapter' 然后使用 'SimpleCursorAdapter' 更好,因为有额外的控制。当我解决了这个问题时,我会告诉你的。再次感谢。
  • @Djole 这家伙错了:SCA 在 99% 的情况下都比 CA 好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-18
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多