【问题标题】:Good way to create a dynamic listview with data from SQLite?使用来自 SQLite 的数据创建动态列表视图的好方法?
【发布时间】:2015-03-30 22:58:14
【问题描述】:

我想用 Notes 编写简单的管理器。 我有一个 SQLite 数据库,其中包含一些数据,如下所示:

_id | time | date | text
 1  | 9:45 | 12.01| blabla
 2  | 21:01| 13.01| albalb
 ...| ...  | ...  | ...

我还有一门课Note:

public class Note {
    private int id;
    private String time;
    private String date;
    private String text;
    public Note(final int id, final String time, final String date, final String text){
        setId(id);
        setTime(time);
        setDate(date);
        setText(text);
    }
    public int getId(){
        return id;
    }
    public String getTime(){
        return time;
    }
    public String getDate(){
        return date;
    }
    public String getText(){
        return text;
    }

    void setId(final int id){
        this.id = id;
    }
    void setTime(final String time){
        this.time = time;
    }
    void setDate(final String date){
        this.date = date;
    }
    void setText(final String text){
        this.text = text;
    }
}

还有 NotesManager:

public class NotesManager {
    private static final String TABLE_NAME = "NotesListTable";
    private static final String KEY_TIME = "time";
    private static final String KEY_DATE = "date";
    private static final String KEY_TEXT = "text";
    private static final String KEY_ID = "_id";

    private final SQLiteDatabase db;
    public NotesManager(SQLiteDatabase db){
        this.db = db;
    }
    public void save(final ContentValues cv){
        db.insert(TABLE_NAME, null, cv);
    }
    public void delete(final int id){
        db.delete(TABLE_NAME, KEY_ID + "=" + id, null);
    }
    public Note getNoteById(final int id){
        Cursor mCursor = db.query(TABLE_NAME, null, KEY_ID + "=" + id, null, null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return new Note(mCursor.getInt(mCursor.getColumnIndex(KEY_ID)),
                mCursor.getString(mCursor.getColumnIndex(KEY_TIME)),
                mCursor.getString(mCursor.getColumnIndex(KEY_DATE)),
                mCursor.getString(mCursor.getColumnIndex(KEY_TEXT)));
    }
    public Cursor getAllDataFromDB(){
        return db.query(TABLE_NAME, null, null, null, null, null, null);
    }
    public String[] getKeysArray(){
        return new String[] {KEY_ID, KEY_TIME, KEY_DATE, KEY_TEXT};
    }
}

我有一个带有 ListView 的片段: 它是由 Android Studio 生成的,我做了一些更改,添加了 SimpleCursorAdapter

public class NotesListFragment extends Fragment implements AbsListView.OnItemClickListener {

    private static final String ARG_SECTION_NUMBER = "section_number";
    private int mSectionNumber = 0;
    private OnFragmentInteractionListener mListener;
    private AbsListView mListView;
    private SimpleCursorAdapter scAdapter;
    private Cursor cursor;
    ImageButton deleteButton;
    NotesManager notesManager = new NotesManager(OrganizerApp.db);

    public static NoesListFragment newInstance(int param1) {
        NoesListFragment fragment = new NotesListFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, param1);
        fragment.setArguments(args);
        return fragment;
    }

    public NotesListFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mSectionNumber = getArguments().getInt(ARG_SECTION_NUMBER);
        }
        cursor = NotesManager.getAllDataFromDB();
        //TODO:  startManagingCursor(cursor)

        //mAdapter = new ArrayAdapter<NotesListContent.NotesItem>(getActivity(),
        //        android.R.layout.simple_list_item_1, android.R.id.text1, NotesListContent.ITEMS);
        scAdapter = new SimpleCursorAdapter(getActivity(),
                R.layout.note_list_rowlayout,
                cursor,
                notesManager.getKeysArray(),
                new int[]{R.id.note_list_rowlayout_item1,
                        R.id.note_list_rowlayout_item2,
                        R.id.note_list_rowlayout_item3,
                        R.id.note_list_rowlayout_item4 });
        deleteButton = (ImageButton) getView().
                findViewById(R.id.note_list_rowlayout_deleteButton);
        deleteButton.setOnClickListener(onClickDeleteButton);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_note, container, false);

        // Set the adapter
        mListView = (AbsListView) view.findViewById(android.R.id.list);
        mListView.setAdapter(scAdapter);
        //((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter);

        // Set OnItemClickListener so we can be notified on item clicks
        mListView.setOnItemClickListener(this);

        return view;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mSectionNumber = getArguments().getInt(ARG_SECTION_NUMBER);
            mListener = (OnFragmentInteractionListener) activity;
            ((MainActivity) activity).onSectionAttached(mSectionNumber);
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }


    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (null != mListener) {
            // Notify the active callbacks interface (the activity, if the
            // fragment is attached to one) that an item has been selected.
           // mListener.onFragmentInteraction(NotesListContent.ITEMS.get(position).id);
        }
    }

    public void setEmptyText(CharSequence emptyText) { // If list is empty.
        View emptyView = mListView.getEmptyView();

        if (emptyView instanceof TextView) {
            ((TextView) emptyView).setText(emptyText);
        }
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(String id);
    }

    View.OnClickListener onClickDeleteButton = new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    };

}

Android studio 也生成了 NotesListContent.java:

public class NotesListContent {

    public static List<Note> ITEMS = new ArrayList<Note>();

    //public static Map<String, Note> ITEM_MAP = new HashMap<String, Note>();

    private static void addItem(Note item) {
        ITEMS.add(item);
        //ITEM_MAP.put(item.id, item);
    }



    /**
     * A dummy item representing a piece of content.

    public static class NoteItem {
        public String id;
        public String content;

        public NoteItem(String id, String content) {
            this.id = id;
            this.content = content;
        }

        @Override
        public String toString() {
            return content;
        }
    }*/
}

所以我的解决方案有效,但我认为它很糟糕。

  1. 我需要 NotesListContent.java 做什么?我该如何使用它?
  2. 如何在没有弃用 simpleCursorAdapter 的情况下使用 ListView?
  3. 如何在不刷新allListView的情况下删除和添加项目?
  4. 尤其是这段代码似乎很不方便:

    scAdapter = new SimpleCursorAdapter(getActivity(), R.layout.note_list_rowlayout, 光标, notesManager.getKeysArray(), 新的 int[]{R.id.note_list_rowlayout_item1, R.id.note_list_rowlayout_item2, R.id.note_list_rowlayout_item3, R.id.note_list_rowlayout_item4 });

【问题讨论】:

  • 不方便?该构造函数有什么不方便的地方?

标签: android sqlite listview android-listview simplecursoradapter


【解决方案1】:

我自己做过笔记管理器,所以我会试着回答你的问题。

我需要一个 NotesListContent.java 吗?我该如何使用它?

这有点像MVC 模式,将数据与视图分离。尝试将其视为一个实体,或者更好地作为单个注释条目描述。

如何在没有弃用 simpleCursorAdapter 的情况下使用 ListView?

a) simpleCursorAdapter 从什么时候开始贬值?它的构造函数只有一个。
b) 您可以使用第二个构造函数,或者自己扩展一些适配器类(例如 ArrayAdapter)

如何在不刷新所有ListView的情况下删除和添加项目?

您将数据添加到您的 dataAdapter,然后将 dataAdapter 设置为 ListView 的适配器 (listview.setAdapter(adapter))。
如果你不调用adapter.notifyDataSetChanged() listview的视图将不会被更新。

尤其是这段代码似乎很不方便(...)

这有什么问题?但如果是这样,请随意使用:

String[] columns = new String[] {  // The desired columns to be bound
        "timestamp",
        "title",
        "content",
};

// the XML defined views which the data will be bound to
int[] map_to = new int[] {
        R.id.timestamp,
        R.id.title,
        R.id.content,
};

dataAdapter = new SimpleCursorAdapter(
        this, R.layout.some_xml_here,
        db.getAllItems(),
        columns,
        map_to,
        0);

【讨论】:

  • 感谢您的回答!可能我不应该使用“数据库->临时游标-> ListView”的方式,而应该做类似“数据库->临时游标->笔记列表(NotesListContent.java中的List)-> ListView”之类的东西?因为所以我将有一个易于使用的笔记列表。如果这比我如何创建 List 更好?以及如何修改 ArrayAdapter 以将多个字段放入每一行?我记得 Android 推荐使用 CursorAdapet。
  • 这取决于你的整个应用程序编写得有多紧密 - 但一般来说,最好使用 ArrayList。要创建 ArrayList 您必须创建 CustomCursorAdapter 并扩展基本适配器,假设您希望它以与 simpleCursorAdapter 相同的方式从 DB 填充,否则只需 List list = new ArrayList() 。您可以找到多个关于如何做到这一点的示例,提供 getView() 的实现就足够了,它很短,但可以根据您的需要进行调整
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 2020-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多