我有一个带有 ViewPager 和 FragmentPagerAdapter 的 FragmentActivity。
ViewPager 中的每个片段都需要从 Web 服务加载数据。我已经编写了 LoaderManager/自定义 Loaders 来执行 Web 服务调用、解析 XML 等,这些工作正常。
有两种可能的设计来管理加载和片段。
1) 代表片段管理加载的主要活动。
该片段回调主 FragmentActivity 请求其数据。该活动检查该数据的加载程序是否已在运行,如果没有,则创建一个加载程序并执行加载。
在这种情况下,我如何告诉片段数据已加载并准备好绘制。我使用的是自定义加载器而不是简单光标,因此片段将从对象实例填充其文本视图等,因此必须告知对象何时已填充。
当您在 getItem 中实例化片段时,FragmentPagerAdapter 似乎不允许您为片段分配标签或 Id。如何从 FragmentActivity 中找到片段并告诉它绘制其数据?
2) 每个片段管理自己的加载。
Fragment初始化自己的Loader,每个fragment都有自己的onCreateLoader/onLoaderFinish等。
我在这里遇到的问题是,如果用户在加载程序运行时离开该页面,则片段似乎被破坏(有时)。因此,不会调用 onLoaderFinished,并且片段无法告诉主活动它已完成 - 主活动正在控制操作栏中的进度指示器 (setProgressBarInminatedVisibility)。
那么,当您有一个 FragmentPagerAdapter(一个具有多个需要自己的加载器的页面的 ViewPager)时,最好的设计模式是什么?
我遇到的另一个问题是使用 getSupportLoaderManager 检查是否有任何加载程序正在运行。我从 onLoadFinished 中调用它。如果没有加载程序运行,我可以隐藏进度指示器。然而,即使所有加载器都已完成,hasRunningLoaders 有时也会返回 true。
LoaderManager lm = getSupportLoaderManager();
// If the loader is not already running, start it...
if (! lm.hasRunningLoaders()) {
setProgressBarIndeterminateVisibility(Boolean.FALSE);
}
Run Code Online (Sandbox Code Playgroud)
非常感谢您提供任何建议或为我指明一些不错的样本的方向。
塔·马丁.
android android-fragments android-viewpager android-loadermanager
我想LoaderManager在我的应用程序中实施以减少启动时间正如您在此处看到的,但在该线程中实施建议后,我收到以下错误initLoader(int, Bundle, LoaderManager.LoaderCallbacks) in the type LoaderManager is not applicable for the arguments (int, null, MainActivity)。在这里搜索后,我发现对于第二个错误的解决方案在这里。但是在实施了后来的建议之后,现在我收到了错误java.lang.NullPointerException
at android.support.v4.content.Loader。我正在提供我目前拥有的代码,谁能告诉我,我该如何解决这个问题
完整代码可以在 这里看到
原木猫
10-03 20:11:34.849: E/AndroidRuntime(2968): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.sms.it/com.test.sms.it.MainActivity}: java.lang.NullPointerException
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.os.Handler.dispatchMessage(Handler.java:99)
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.os.Looper.loop(Looper.java:123)
10-03 20:11:34.849: E/AndroidRuntime(2968): at android.app.ActivityThread.main(ActivityThread.java:3683)
10-03 20:11:34.849: E/AndroidRuntime(2968): …Run Code Online (Sandbox Code Playgroud) 代码:
首先是我的Uris
public static final String PACKAGE = "my.url.contentprovider";
public static final String TABLE_NAME = "NetworkTransaction";
public static final String AUTHORITY = PACKAGE + ".NetTransContentProvider";
public static final Uri BASE_URI = Uri.parse("content://"+AUTHORITY);
public static final Uri CONTENT_URI_ANY_OBSERVER = Uri.withAppendedPath(BASE_URI,TABLE_NAME+"/*");
public static final Uri CONTENT_URI_FIND_BY_ID = Uri.withAppendedPath(BASE_URI,TABLE_NAME+"/FIND/ID");
public static final Uri CONTENT_URI_INSERT_OR_REPLACE_BY_ID = Uri.withAppendedPath(BASE_URI,TABLE_NAME+"/INSERT/REPLACE/ID");
public static final Uri CONTENT_URI_INSERT_BY_ID = Uri.withAppendedPath(BASE_URI,TABLE_NAME+"/INSERT/ID");
Run Code Online (Sandbox Code Playgroud)
和我的活动代码加载器:
@Override
protected void onResume() {
super.onResume();
getSupportLoaderManager().restartLoader(NET_TRANS_LOADER_ID,mBundle,this).forceLoad();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
Uri uri = …Run Code Online (Sandbox Code Playgroud) android android-contentresolver android-contentprovider android-loadermanager android-loader
我想将API中的信息加载到Fragment.
我使用getSupportLoaderManager()但发生错误:
无法解析方法:getSupportLoaderManager()
我搜索这个用途,onActivityCreated()但我有NullPointerException.
你能帮我解决一下这个问题吗?
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
public class Business extends Fragment implements LoaderManager.LoaderCallbacks<String> {
ListView listView;
public Business() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_business, container, false);
listView = view.findViewById(R.id.list_item);
getSupportLoaderManager().initLoader(0, null, getContext()).forceLoad();
return view;
}
@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return null; …Run Code Online (Sandbox Code Playgroud) 我试图将我的Android应用程序转换为使用LoaderManager和CursorLoader.基本上,我有一个包含ADDRESS列和DISTANCE列的SQLite数据库,我想将列值加载到ListView行中.
现在,我已经做了很多研究,所有内容都指向了这个教程:http://mobile.tutsplus.com/tutorials/android/android-sdk_content-providers/
这是一个很好的教程,但有几件事我还是不明白.主要是,如何构造传递给'new CursorLoader()'的内容URI?我没有使用任何外部数据,例如设备联系人等.
请参阅下面的代码.我对如何为BASE_URI生成值感到困惑:
public class FavoritesFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter;
static final String[] FAVORITES_SUMMARY_PROJECTION = new String[] {
MyApplication.COLUMN_ID, MyApplication.COLUMN_ADDRESS,
MyApplication.COLUMN_DISTANCE, };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new SimpleCursorAdapter(getActivity(),
R.layout.locations_list_row, null, new String[] {
MyApplication.COLUMN_ADDRESS,
MyApplication.COLUMN_DISTANCE }, new int[] {
R.id.address2, R.id.distance }, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Insert desired behavior here.
}
public …Run Code Online (Sandbox Code Playgroud) 我正在编写一个Android应用程序sqlite.有许多活动和一项服务.我使用来自多个线程的数据库.它完美地Android 2.X运行,但是一旦我在它中运行Android 3.X它总是抛出这个错误,并且Force Close:
05-04 22:17:04.815: I/SqliteDatabaseCpp(8774): sqlite returned: error code = 5, msg = database is locked, db=/data/data/xxx/databases/im
05-04 22:17:04.815: E/SqliteDatabaseCpp(8774): sqlite3_open_v2("/data/data/xxx/databases/im", &handle, 6, NULL) failed
05-04 22:17:04.835: E/SQLiteDatabase(8774): Failed to open the database. closing it.
05-04 22:17:04.835: E/SQLiteDatabase(8774): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
05-04 22:17:04.835: E/SQLiteDatabase(8774): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
05-04 22:17:04.835: E/SQLiteDatabase(8774): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
05-04 22:17:04.835: E/SQLiteDatabase(8774): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
05-04 22:17:04.835: E/SQLiteDatabase(8774): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
05-04 22:17:04.835: E/SQLiteDatabase(8774): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:790)
05-04 22:17:04.835: …Run Code Online (Sandbox Code Playgroud) 我有一个AsyncTaskLoader<List<String>>成员变量List<String>mAddresses.在loadInBackground,如果我创建一个新对象,填充它,并返回它; onLoadFinished按预期调用,所以我可以更新适配器,然后更新视图.
public List<String> loadInBackground()
{
// ListView updates properly only if I do this (strange?)
mAddresses = new ArrayList<String>();
// ... fill mAddresses ...
return mAddresses;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用相同的变量,即使它的值发生变化也会onLoadFinished被调用:
public List<String> loadInBackground()
{
// ListView does not update with this!
if(mAddresses == null)
{
mAddresses = new ArrayList<String>();
}
// ... fill mAddresses ...
return mAddresses;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以评论这个吗?我是否应该像这样创建一个新对象来返回?是否有任何标志我可以设置"对象已更改,所以即使它是同一个对象,请确保执行所有更新?
android asynctaskloader android-loadermanager android-loader
我SimpleCursorAdapter为我扩展的自定义适配器ListFragment无法正确显示数据库中的项目.它不会在TextView中显示文本,我还需要对光标做什么才能显示正确的文本?
我以为我必须覆盖bindView但没有效果
设置适配器:
public void populateList(){
String[] fields = new String[] {BowlersDB.NAME};
Cursor c = getActivity().getContentResolver().query(BowlersDB.CONTENT_URI,
new String[] {BowlersDB.ID,BowlersDB.NAME},null,null,BowlersDB.NAME + " COLLATE LOCALIZED ASC");
mAdapter = new CheckAdapter(getActivity(),R.layout.check_listview,c,fields,new int[] {R.id.nameCheckTV});
setListAdapter(mAdapter);
getLoaderManager().initLoader(0,null,this);
}
Run Code Online (Sandbox Code Playgroud)
适配器:
public class CheckAdapter extends SimpleCursorAdapter{
Context context;
Cursor c;
public CheckAdapter(Context context, int layout, Cursor c,String[] from, int[] to) {
super(context, layout, c, from, to);
this.context = context;
this.c = c;
// TODO Auto-generated constructor stub
}
@Override
public void …Run Code Online (Sandbox Code Playgroud) android android-listview android-cursor android-loadermanager android-cursoradapter
我对Android很新,我对过滤的listView和从横向模式更改为纵向模式或反之亦然的活动有一些问题.我有一个editText用于过滤"drinkSearch",只要我不改变视角(人像与风景),这个过滤就有效.这是我得到的错误:
java.lang.IllegalStateException:尝试重新打开已经关闭的对象:SQLiteQuery:SELECT _id,name FROM drinks
正如您在下面的代码中看到的,我使用了接口LoaderManager.LoaderCallbacks,这个概念对我来说有点新,我不确定哪里出了问题.我将非常感谢所有的帮助,在此先感谢!
public class Drinks_Fragment extends Fragment实现LoaderManager.LoaderCallbacks {
private static final int DRINKS_LIST_LOADER = 0x01;
private SimpleCursorAdapter adapter;
private ListView drinksList;
private String LOG;
private EditText drinkSearch;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.drinks_list, container, false);
drinkSearch = (EditText)view.findViewById(R.id.drinkInputSearch);
drinksList = (ListView) view.findViewById(R.id.drinksList);
drinksList.setEmptyView(view.findViewById(R.id.empty_list_view));
String[] from = {DrinksTable.COLUMN_NAME};
int[] to = {R.id.drinkName};
getLoaderManager().initLoader(DRINKS_LIST_LOADER, null, this);
adapter = new SimpleCursorAdapter(getActivity().getApplicationContext(), R.layout.drinks_list_item,null, from, to, 0);
drinksList.setAdapter(adapter);
Run Code Online (Sandbox Code Playgroud)
在这部分中,我根据searchDrink editText中输入的字符串向contentProvider询问新的Cursor.(以下代码,直到"返回视图"正好在上面的部分下方,同样的onCreateView方法)
drinkSearch.addTextChangedListener(new TextWatcher() { …Run Code Online (Sandbox Code Playgroud) android android-contentprovider android-listview android-loadermanager android-sqlite
当我尝试使用非静态内部Loader类时,我收到以下运行时错误:
从onCreateLoader返回的对象不能是非静态内部成员类
这个限制有什么意义?