如何快速添加新项目到列表视图
How to add new item to listview quickly
我想用 Notes 编写简单的管理器。
所以我的解决方案有效,但非常糟糕,因为在 NewNoteActivity 中创建新笔记后,我使用 ListView return 到 activity,我看到我的列表是如何再次构建的。
我读到 listview 总是会重建,但为什么在我的情况下需要这么多时间?比如在其他应用中我没有见过绘制列表的过程,但是在我的应用中我看到了。
那么在好的应用中如何快速构建listview呢?我的代码有什么问题?我只想在 NewNoteActivity 中添加新项目,return 到 activity with list 并查看准备好的列表!
我有一个 SQLite 数据库,其中包含一些数据,如下所示:
_id | time | date | text
1 | 9:45 | 12.01| blabla
2 | 21:01| 13.01| albalb
...| ... | ... | ...
我还有一个class 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) {
}
};
}
我有一个 activity 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);
我会在这里给出一些提示。
当您使用数据库加载数据时,我首先想到的是您在创建列表时要获取大量记录。
乘以4,就是每个listView的item中的view数,可能是速度变慢的原因。
通常,您希望开始从另一个线程获取数据,目的是保持 MainThread 的轻量和自由(这意味着您的应用程序将在发生重负载时响应)。
这可以通过 AsyncThread 完成。我建议您在加载和显示数据时弹出 ProgressBar 视图,以通知用户您的应用正在进行中。
另一种 很棒 让你的 listView 更快的方法(至少在滚动期间,不确定它是否可以在加载阶段帮助你),是在你的适配器。
每次滚动,Android 调用 Adapter 的 getView() 方法,通常在每次找到项目时创建一个新视图(请记住,一个项目内部有 4 个视图!)。当您处理许多物品时,这会使它变得非常慢。 ViewHolder 模式背后的想法是重用不再可见的视图,而不是添加新视图。
您可以找到更多相关信息 here。
如果还是不行,我会尝试另一种加载方式。
来自数据库的大约 1000 多行对于您首先需要显示的内容来说可能是一个超负荷的工作。
例如,假设您有 1000 条记录要插入到 listView 中。全部加载它们可能需要一些时间,当完成并填充 listView 时,您将永远无法查看它们,只是因为您的 listView 具有特定的 space 并且在显示器上您会只能看到一小部分数据,比方说 10。
我的观点是:为什么要让 phone 忙于在视图创建时加载 1000 条记录,当你可以加载时假设 50(考虑早期滚动),当你知道 listView 已创建并且你能够与应用程序交互,将其余部分加载到后台线程(仍然是 AsyncTask)。完成后,将数据更改通知适配器。
希望大家理解^_^
我想用 Notes 编写简单的管理器。
所以我的解决方案有效,但非常糟糕,因为在 NewNoteActivity 中创建新笔记后,我使用 ListView return 到 activity,我看到我的列表是如何再次构建的。 我读到 listview 总是会重建,但为什么在我的情况下需要这么多时间?比如在其他应用中我没有见过绘制列表的过程,但是在我的应用中我看到了。
那么在好的应用中如何快速构建listview呢?我的代码有什么问题?我只想在 NewNoteActivity 中添加新项目,return 到 activity with list 并查看准备好的列表!
我有一个 SQLite 数据库,其中包含一些数据,如下所示:
_id | time | date | text
1 | 9:45 | 12.01| blabla
2 | 21:01| 13.01| albalb
...| ... | ... | ...
我还有一个class 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) {
}
};
}
我有一个 activity 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);
我会在这里给出一些提示。
当您使用数据库加载数据时,我首先想到的是您在创建列表时要获取大量记录。
乘以4,就是每个listView的item中的view数,可能是速度变慢的原因。
通常,您希望开始从另一个线程获取数据,目的是保持 MainThread 的轻量和自由(这意味着您的应用程序将在发生重负载时响应)。
这可以通过 AsyncThread 完成。我建议您在加载和显示数据时弹出 ProgressBar 视图,以通知用户您的应用正在进行中。
另一种 很棒 让你的 listView 更快的方法(至少在滚动期间,不确定它是否可以在加载阶段帮助你),是在你的适配器。
每次滚动,Android 调用 Adapter 的 getView() 方法,通常在每次找到项目时创建一个新视图(请记住,一个项目内部有 4 个视图!)。当您处理许多物品时,这会使它变得非常慢。 ViewHolder 模式背后的想法是重用不再可见的视图,而不是添加新视图。
您可以找到更多相关信息 here。
如果还是不行,我会尝试另一种加载方式。
来自数据库的大约 1000 多行对于您首先需要显示的内容来说可能是一个超负荷的工作。
例如,假设您有 1000 条记录要插入到 listView 中。全部加载它们可能需要一些时间,当完成并填充 listView 时,您将永远无法查看它们,只是因为您的 listView 具有特定的 space 并且在显示器上您会只能看到一小部分数据,比方说 10。 我的观点是:为什么要让 phone 忙于在视图创建时加载 1000 条记录,当你可以加载时假设 50(考虑早期滚动),当你知道 listView 已创建并且你能够与应用程序交互,将其余部分加载到后台线程(仍然是 AsyncTask)。完成后,将数据更改通知适配器。
希望大家理解^_^