【问题标题】:How to add new item to listview quickly如何快速将新项目添加到列表视图
【发布时间】:2015-02-04 16:57:04
【问题描述】:

我想用 Notes 编写简单的管理器。

所以我的解决方案有效,但非常糟糕,因为在 NewNoteActivity 中创建新笔记后,我返回到使用 ListView 的活动,我看到我的列表是如何再次构建的。 我读到 listview 总是会被重建,但为什么在我的情况下需要这么多时间?例如,在其他应用程序中我从未见过绘制列表的过程,但在我的应用程序中却看到了。

那么如何在好的应用程序中如此快速地构建列表视图呢?我的代码有什么问题?我只想在 NewNoteActivity 中添加新项目,返回带有列表的活动并查看准备好的列表!

我有一个 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)

        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);


        // 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) {

        }
    };

}

我有一个活动NewNoteActivity,我在其中创建了一个新笔记并将其放入数据库:

ContentValues cv = new ContentValues();

            cv.put("time", entTime.getText().toString());
            cv.put("date", entDate.getText().toString());
            cv.put("comment", entComment.getText().toString());
            NotesManager.save(cv);

【问题讨论】:

    标签: android sqlite listview android-listview


    【解决方案1】:

    我会在这里给出一些提示。

    当您使用数据库加载数据时,我首先想到的是您在创建列表时要获取大量记录。

    乘以4,每个listView的item的view数,可能是速度变慢的一个原因。

    通常,您希望开始从另一个线程获取数据,旨在保持 MainThread 轻量且免费(这意味着您的应用将在重负载发生时做出响应)。

    这可以通过 AsyncThread 来完成。我建议您在加载和显示数据时弹出一个 ProgressBar 视图,以通知用户您的应用正在进行中。

    另一种伟大的方法可以让您的 listView 更快(至少在滚动期间,不确定它是否可以帮助您在加载阶段),是在您的适配器中实现 ViewHolder 模式。

    每次滚动,Android都会调用Adapter的getView()方法,一般每次找到一个item都会创建一个新的View(记住,一个item里面有4个view!)。当您处理许多项目时,这使得它非常慢。 ViewHolder 模式背后的想法是重用不再可见的视图,而不是添加新的视图。

    您可以在here找到更多相关信息。

    如果这仍然没有帮助,我会尝试另一种加载方式。

    从数据库中获取大约 1000 多行可能会使您首先需要显示的工作超负荷。

    例如,假设您有 1000 条记录要插入到 listView 中。加载它们可能需要一些时间,当完成并且 listView 被填满时,你将永远无法看到它们,因为你的 listView 有一定的空间并且在显示器上你只能看到一小部分数据,比如说 10。 我的观点是:为什么要让手机在创建视图时忙着加载 1000 条记录,什么时候可以加载让我们说 50 条(考虑到早期滚动),并且当您知道创建了 listView 并且您能够与应用程序交互时将其余部分加载到后台线程中(仍然是 AsyncTask)。完成后,通知适配器数据更改。

    希望可以理解^_^"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 2021-06-05
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      相关资源
      最近更新 更多