我听说有一些新的解决方案可以在后台加载数据,这比AsyncTask(比如加载器)更值得推荐.
AsyncTasks很棒且易于使用.但是,它有一些局限性:
类本身必须进行修改,因为它受到待处理任务数量的限制(约256左右).当然,在listView的适配器中,如果不需要,我总是取消任务(例如,当我需要更新用于其他项目的视图时).
在重新创建活动/片段时,我还必须全部取消它们(或以不同的方式处理).
由于1和2,我需要管理它们并参考所有这些
AsyncTask使用一个任务队列,有时我需要使用堆栈,所以我不得不创建自己的AsyncTask类,而不是使用堆栈.
是否有AsyncTask的替代品?
我知道之前曾在某些帖子中提到这个问题(比如这里),但我在想是否有一种新的通用方法可以在后台加载数据来替换asyncTask.
关于Loaders,我认为这个想法是它们用于数据库和contentProviders,但它们是否也可以用于从Internet上加载(例如)数据(如图像文件)?
还有一个很好的样本由谷歌(这里称为"bitmapFun"),根据我所看到的使用AsyncTask(甚至扩展它,可能是因为我提到的相同的原因).但也许我也错过了一些东西?
在我的列表视图没有填充数据库数据时,有什么更好的方法来显示进度指示器?
我找到了一些如何使用assynctask执行此操作的示例,但在我的情况下,我使用Loader/ CursorLoader.
public class TestActivity extends SherlockFragmentActivity implements
LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter;
ListView mListView;
private static final String[] UI_BINDING_FROM = new String[] {
TestDBAdapter.KEY_NAME, TestDBAdapter.KEY_ICON };
private static final int[] UI_BINDING_TO = new int[] { R.id.text, R.id.icon };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_Test);
mListView = (ListView) findViewById(R.id.listview);
mAdapter = new TestAdapter(getApplicationContext(),
R.layout.list_item_Test, null, UI_BINDING_FROM,
UI_BINDING_TO, 0);
mListView.setAdapter(mAdapter);
getSupportLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri uri = ContentProviderTest.CONTENT_URI; …Run Code Online (Sandbox Code Playgroud) 目前,我有一个装载机
@Override
public Loader<List<HomeMenuRowInfo>> onCreateLoader(int arg0, Bundle bundle) {
return new HomeMenuRowInfosLoader(this.getSherlockActivity());
}
Run Code Online (Sandbox Code Playgroud)
有时,由于内容更改,我需要让加载程序重新加载.我会做的.
this.getLoaderManager().getLoader(0).onContentChanged();
Run Code Online (Sandbox Code Playgroud)
但是,我希望onCreateLoader在内容更改时将一些其他捆绑信息传递给回调.我意识到通过使用onContentChanged,没有办法这样做.
我能搞清楚的唯一方法是
this.getLoaderManager().restartLoader(0, bundle, this);
Run Code Online (Sandbox Code Playgroud)
我想知道,是否有任何重大分歧Loader的行为,使用的restartLoader不是onContentChanged,除了捆绑传递的能力吗?
让我首先说这不是关于滚动ListViews的问题.我不想知道如何判断用户何时滚动到列表的底部,所以请不要给我这个问题的答案,或者将其标记为重复.
我正在使用一个扩展AsyncTaskLoader的类来使用来自Web服务的数据填充ListView.
最初,我加载50件物品,一切都很好.我需要知道如何告诉Loader以递增方式加载下50个项目.我理解在ListView代码中要执行此操作,但我无法找出告诉Loader我想要加载更多数据而不重置它并再次加载所有内容的最佳方法.
再说一次,澄清一下,我在这里要解决的问题只是通知加载器需要加载更多数据.它已经知道如何在第二次调用loadInBackground()时加载更多数据,并且ListView已经知道在何时/何时通知Loader,问题是如何.
一些相关代码:
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
m_adapter = new SearchAdapter(getActivity());
setListAdapter(m_adapter);
// if the loader doesn't already exist, one will be created
// otherwise the existing loader is reused so we don't have
// to worry about orientation and other configuration changes
getLoaderManager().initLoader(SEARCH_LOADER_ID, null, this);
}
@Override
public Loader<List<Result>> onCreateLoader(int id, Bundle args)
{
String query = args != null ? args.getString(QUERY_KEY) : "";
return new SearchLoader(getActivity(), query); …Run Code Online (Sandbox Code Playgroud) 我正在开发一个基于GoogleMap的Android应用程序.
我需要在地图上显示1000个标记.
目前,我从SQLite数据库加载器中检索每个标记的纬度和经度,并在public void onLoadFinished(final Loader loader, final Cursor cursor)方法中添加标记.
这种方法虽然提供了非常糟糕的用户体验,因为当我添加标记时应用程序没有响应.
如何在googlemap中添加1000个标记并保持我的应用程序响应?
因为我必须在主UI线程上将标记添加到地图.
在配置更改后重新创建时,它们会自动重新连接到最后一个加载器的光标.因此,他们不需要重新查询他们的数据.
在这篇关于装载机的博客文章中,
当一个Activity被销毁时,Activity指示它的LoaderManager销毁并关闭它的Loaders(以及与它们相关的任何资源,比如Cursor).
问题是哪一个是正确的?当一个活动因配置更改而被销毁时,(1)其Loaders(2)与其Loaders关联的资源(例如a)会发生什么Cursor.
android android-configchanges android-activity android-loadermanager android-loader
精简版:
我有保持一个片段ViewPager显示其他两个片段,让我们称他们FragmentOne和FragmentTwo.当启动应用程序时,该应用程序FragmentOne是可见的并且FragmentTwo在屏幕外,只有在向左滑动视图时才可见.
通常onStart(),onResume()应用程序启动后立即立即调用这两个片段.
我遇到的问题是当FragmentOne启动自定义时,Loader然后onResume()在FragmentTwo它变得完全可见之前不会被调用.

问题:
这是我的代码问题还是Android支持库中的错误?(该库的修订版12没有出现问题,它从修订版13开始.)
如果它是修订版13和18中的错误,是否有解决方法?
我的自定义有问题Loader吗?
长版:
我已经构建了一个演示该问题的示例应用程序.我试图将代码减少到最低限度,但它仍然很多,所以请耐心等待.
我有一个MainActivity加载a MainFragment创建一个ViewPager.对于我的应用程序来说,ViewPager由Fragment而不是Activity维护是很重要的.
MainFragment创建一个FragmentPagerAdapter反过来创建片段FragmentOne和FragmentTwo.
让我们从有趣的位开始,两个片段:
FragmentOne是一个ListFragment使用自定义Loader加载内容:
public class FragmentOne extends ListFragment implements LoaderCallbacks<List<String>> {
private ArrayAdapter<String> adapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1);
setListAdapter(adapter); …Run Code Online (Sandbox Code Playgroud) android android-viewpager android-loader android-support-library
我想AsyncTaskLoader为我的自定义数据源实现:
public class DataSource {
public interface DataSourceObserver {
void onDataChanged();
}
...
}
Run Code Online (Sandbox Code Playgroud)
DataSource将保留已注册观察员的名单,并将通知他们有关变化的信息.CustomLoader将实施DataSourceObserver.问题是如何正确通知,CustomLoader因为Loader.onContentChanged()必须从UI线程调用,但在我的情况下,DataSource操作(和调用DataSourceObserver.onDataChanged())将从后台线程完成.
更新了Selvin提示的想法:
public class CustomLoader extends AsyncTaskLoader<...> implements DataSource.DataSourceObserver {
private final Handler observerHandler;
public CustomLoader(Context context) {
super(context);
observerHandler = new Handler()
}
@Override
public void onDataChanged() {
observerHandler.post(new Runnable() {
@Override
public void run() {
onContentChanged();
}
});
}
}
Run Code Online (Sandbox Code Playgroud) 如果这看起来微不足道,我深表歉意。
我一直在开发我的第一个 Android 应用程序,并希望获得有关实现附加加载/启动屏幕的最佳方法的建议。
我的设计师想出了加载/启动屏幕,但我不知道如何实现它。
请注意,自行车从左侧开始并继续向右,并带有进度指示器和%。
选项 2 是否可行?如果可以,请您指出我可以用作指南的任何资源。
谢谢
在活动A中,我正在加载一个包含我表中所有值的列表,并设置了一个setOnItemClickListener来启动活动B并通过发送数据发送带有所选项的id [ 1 ] 的uri
[ 1 ]
Uri currentTestUri = ContentUris.withAppendedId(TestEntry.CONTENT_URI, id);
在活动B中,我的onCreateLoader包含投影:
String[] projection = {
TestEntry._ID,
TestEntry.COLUMN_TEST_ONE,
TestEntry.COLUMN_TEST_TWO}
Run Code Online (Sandbox Code Playgroud)
...带有return语句
return new CursorLoader(this,
mCurrentTestUri, //Got this from Activity A
projection,
null,
null,
null);
Run Code Online (Sandbox Code Playgroud)
我的onLoadFinished看起来像这样:
if (cursor.moveToFirst()) {
int oneColumnIndex = cursor.getColumnIndex(TestEntry.COLUMN_TEST_ONE);
int twoColumnIndex = cursor.getColumnIndex(TestEntry.COLUMN_TEST_TWO);
String currentOne = cursor.getString(oneColumnIndex);
String currentTwo = cursor.getString(twoColumnIndex);
textViewOne.setText(currentOne);
textViewTwo.setText(currentTwo);
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,现在我希望显示下一行(右下方)的值,但是使用不同的投影(我只需要_ID和COLUMN_TEST_ONE)并且onLoadFinished显示COLUMN_TEST_ONE的值textViewThree.
[两行的值应该同时显示,而不是一个或另一个]
我可以使用[ …
sqlite android android-cursorloader android-loader android-sqlite