【发布时间】:2013-09-30 17:12:21
【问题描述】:
我正在尝试使 LoaderManager 列表向后兼容 Android 2.1。列表加载正常,但即使列表中有项目清晰可见,@id/android:empty 消息也会显示。
我在 StackOverflow 上查看了许多使用 setEmptyView() 和 setEmptyText() 但无法让它们工作的解决方案。
这是 ListFragment 的代码。我一直在组合来自各种http://www.vogella.com/ 教程的代码。
package com.example.contentprov;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.example.contentprov.data.MyTodoContentProvider;
import com.example.contentprov.data.TodoTable;
/*
* TodosOverviewActivity displays the existing todo items
* in a list
*
* You can create new ones via the ActionBar entry "Insert"
* You can delete existing ones via a long press on the item
*/
public class TodoOverviewFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
private SimpleCursorAdapter adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setContentView(R.layout.todo_list);
fillData();
}
// Opens the second activity if an entry is clicked
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent i = new Intent(getActivity(), TodoDetailActivity.class);
Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
startActivity(i);
}
private void fillData() {
// Fields from the database (projection)
// Must include the _id column for the adapter to work
String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
// Fields on the UI to which we map
int[] to = new int[] { R.id.label };
getActivity().getSupportLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(getActivity(), R.layout.todo_row, null, from,
to, 0);
setListAdapter(adapter);
}
// Creates a new loader after the initLoader () call
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY };
CursorLoader cursorLoader = new CursorLoader(getActivity(),
MyTodoContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
Intent i = new Intent(getActivity(), TodoDetailActivity.class);
Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
startActivity(i);
}
}
这是列表的 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/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_todos" />
</LinearLayout>
编辑:解决方案是结合 Eluvatar 和 dymmeh 的答案。这是 ListFragment 的新版本。
package com.example.contentprov;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.example.contentprov.data.MyTodoContentProvider;
import com.example.contentprov.data.TodoTable;
/*
* TodosOverviewActivity displays the existing todo items
* in a list
*
* You can create new ones via the ActionBar entry "Insert"
* You can delete existing ones via a long press on the item
*/
public class TodoOverviewFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
private SimpleCursorAdapter adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fillData();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.todo_list,
container, false);
return view;
}
// Opens the second activity if an entry is clicked
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent i = new Intent(getActivity(), TodoDetailActivity.class);
Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
startActivity(i);
}
private void fillData() {
// Fields from the database (projection)
// Must include the _id column for the adapter to work
String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
// Fields on the UI to which we map
int[] to = new int[] { R.id.label };
getActivity().getSupportLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(getActivity(), R.layout.todo_row, null, from,
to, 0);
setListAdapter(adapter);
}
// Creates a new loader after the initLoader () call
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY };
CursorLoader cursorLoader = new CursorLoader(getActivity(),
MyTodoContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
Intent i = new Intent(getActivity(), TodoDetailActivity.class);
Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
startActivity(i);
}
}
【问题讨论】:
-
呃,您正在从片段中设置活动的内容视图?!为什么?
-
它在 ListActivity 中,但 ListActivity 与 LoaderManager 不兼容。 LoaderManager 需要使用 ListFragment 来代替(当使用 getSupportLoaderManager 以实现向后兼容性时)。我对Android相当陌生。这能回答你的问题吗?
-
是的,你应该看看使用developer.android.com/guide/components/fragments.html,我没有专门使用
ListFragment,但你应该覆盖OnCreateView并在那里替换你的自定义布局,因为这就是你不使用的原因完全看到您的列表视图(在顶部添加一个文本视图并尝试使其可见),至于其余部分......我从未使用过 LoaderManager 但如果它需要一个片段,我会感到惊讶。跨度> -
我确实看到了列表视图。它只是出现在“TextView”中空消息的顶部。我会看一下片段指南。我在另一个线程中看到了“OnCreateView”,还没有尝试使用它。
-
使用
onCreateView定义要使用的布局。非常感谢。
标签: java android android-listview android-listfragment android-loadermanager