因此,我到了需要为我的应用程序实现SQLite数据库的地步。遵循“
Android开发的繁忙程序员指南”,我创建了一个Extended的DatabaseHelper类SQLiteOpenHelper
。
我的用例之一是对数据库运行查询,并ListView
在内显示结果Fragment
(我使用支持库中的片段)。
据我了解,使用managedQuery()
并不是真正合适的方法,即使不建议使用,因为实际上封装在该方法中的某些逻辑实际上是在主线程上执行的,据reQuery()
我所知具体是在Activity
重新启动。
因此,我一直试图Loader
第一次熟悉该类,只是看到了这一点:
"The only supplied concrete implementation of a Loader is CursorLoader, and that is only for use with a ContentProvider"
我最初的想法是实现自己的内容提供程序,并可能阻止其他应用程序访问它,然后我ContentProvider
通过developer.android.com
阅读了文档中的以下内容:
"You don't need a provider to use an SQLite database if the use is entirely within your own application."
我也一直在玩这个:
https://github.com/commonsguy/cwac-
loaderex
但是我对这个项目并不熟悉,并且不确定是否可以在生产环境中使用它。
因此,现在我所能想到的就是AsyncTask
在我的内部创建一堆实例Fragment
并适当地管理它们的生命周期,确保在需要时取消它们,而不会取消它们。
还有其他选择吗?
您可以扩展Loader类,以执行其他异步工作,例如直接从数据库中加载。
这是一个例子
编辑: 添加了一个更好的Loader使用示例。
最终设法找到了真正帮助我了解事情原理的教程。
通过扩展加载程序类,您可以避免与内容观察者打交道,并且它相当容易实现(最后),需要在代码中进行的修改是
LoaderManager.LoaderCallbacks<D>
,D
您的数据列表在哪里(代码段1)片段1: 如何将加载程序与片段“链接”:
public static class AppListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<List<SampleItem>> {
public Loader<List<SampleItem>> onCreateLoader(int id, Bundle args) {
//...
return new SampleLoader (getActivity());
}
public void onLoadFinished(Loader<List<SampleItem>> loader, List<SampleItem> data) {
// ...
mAdapter.setData(data);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
// ...
}
public void onLoaderReset(Loader<List<SampleItem>> loader) {
// ...
mAdapter.setData(null);
// ...
}
/* ... */
}
片段2:
您的自定义加载程序的架构:(我对观察者的观点进行了两次评论,因为我认为从一开始就很难实现它,您可以简单地调用加载程序而不会弄乱自动刷新)
public class SampleLoader extends AsyncTaskLoader<List<SampleItem>> {
// We hold a reference to the Loader’s data here.
private List<SampleItem> mData;
public SampleLoader(Context ctx) {
// Loaders may be used across multiple Activitys (assuming they aren't
// bound to the LoaderManager), so NEVER hold a reference to the context
// directly. Doing so will cause you to leak an entire Activity's context.
// The superclass constructor will store a reference to the Application
// Context instead, and can be retrieved with a call to getContext().
super(ctx);
}
/****************************************************/
/** (1) A task that performs the asynchronous load **/
/****************************************************/
@Override
public List<SampleItem> loadInBackground() {
// This method is called on a background thread and should generate a
// new set of data to be delivered back to the client.
List<SampleItem> data = new ArrayList<SampleItem>();
// TODO: Perform the query here and add the results to 'data'.
return data;
}
/********************************************************/
/** (2) Deliver the results to the registered listener **/
/********************************************************/
@Override
public void deliverResult(List<SampleItem> data) {
if (isReset()) {
// The Loader has been reset; ignore the result and invalidate the data.
releaseResources(data);
return;
}
// Hold a reference to the old data so it doesn't get garbage collected.
// We must protect it until the new data has been delivered.
List<SampleItem> oldData = mData;
mData = data;
if (isStarted()) {
// If the Loader is in a started state, deliver the results to the
// client. The superclass method does this for us.
super.deliverResult(data);
}
// Invalidate the old data as we don't need it any more.
if (oldData != null && oldData != data) {
releaseResources(oldData);
}
}
/*********************************************************/
/** (3) Implement the Loader’s state-dependent behavior **/
/*********************************************************/
@Override
protected void onStartLoading() {
if (mData != null) {
// Deliver any previously loaded data immediately.
deliverResult(mData);
}
// Begin monitoring the underlying data source.
////if (mObserver == null) {
////mObserver = new SampleObserver();
// TODO: register the observer
////}
//// takeContentChanged() can still be implemented if you want
//// to mix your refreshing in that mechanism
if (takeContentChanged() || mData == null) {
// When the observer detects a change, it should call onContentChanged()
// on the Loader, which will cause the next call to takeContentChanged()
// to return true. If this is ever the case (or if the current data is
// null), we force a new load.
forceLoad();
}
}
@Override
protected void onStopLoading() {
// The Loader is in a stopped state, so we should attempt to cancel the
// current load (if there is one).
cancelLoad();
// Note that we leave the observer as is. Loaders in a stopped state
// should still monitor the data source for changes so that the Loader
// will know to force a new load if it is ever started again.
}
@Override
protected void onReset() {
// Ensure the loader has been stopped.
onStopLoading();
// At this point we can release the resources associated with 'mData'.
if (mData != null) {
releaseResources(mData);
mData = null;
}
// The Loader is being reset, so we should stop monitoring for changes.
////if (mObserver != null) {
// TODO: unregister the observer
//// mObserver = null;
////}
}
@Override
public void onCanceled(List<SampleItem> data) {
// Attempt to cancel the current asynchronous load.
super.onCanceled(data);
// The load has been canceled, so we should release the resources
// associated with 'data'.
releaseResources(data);
}
private void releaseResources(List<SampleItem> data) {
// For a simple List, there is nothing to do. For something like a Cursor, we
// would close it in this method. All resources associated with the Loader
// should be released here.
}
/*********************************************************************/
/** (4) Observer which receives notifications when the data changes **/
/*********************************************************************/
// NOTE: Implementing an observer is outside the scope of this post (this example
// uses a made-up "SampleObserver" to illustrate when/where the observer should
// be initialized).
// The observer could be anything so long as it is able to detect content changes
// and report them to the loader with a call to onContentChanged(). For example,
// if you were writing a Loader which loads a list of all installed applications
// on the device, the observer could be a BroadcastReceiver that listens for the
// ACTION_PACKAGE_ADDED intent, and calls onContentChanged() on the particular
// Loader whenever the receiver detects that a new application has been installed.
// Please don’t hesitate to leave a comment if you still find this confusing! :)
////private SampleObserver mObserver;
}
片段3: 如何首次调用加载程序(仅)
// Initialize a Loader with an id. If the Loader with this id is not
// initialized before
getLoaderManager().initLoader(LOADER_ID, null, this);
片段4: 用于刷新数据(调用查询)
// Check if the loader exists and then restart it.
if (getLoaderManager().getLoader(LOADER_ID) != null)
getLoaderManager().restartLoader(LOADER_ID, null, this);
参考:
创建者还将这些的完整代码上传到github
本文向大家介绍详解Android WebView加载html片段,包括了详解Android WebView加载html片段的使用技巧和注意事项,需要的朋友参考一下 这里我先简单描述一下需求:服务器返回的是html页面的一部分带有标签的内容。 解决的思路是:将服务器返回的内容片段拼凑成一个完整的页面。 下面直接上核心代码: 这里是WebView一些配置 笔者在Nexus6 7.0上面测试偶尔出现,h
问题内容: 我只是很好奇,因为我已经在FragmentActivity中设置了Fragment选项卡,如何从FragmentActivity或Fragment本身重新加载片段,以清除并重新加载该选项卡。我本质上需要重新选择选项卡以替换片段时发生的相同事情。有一种简单的方法可以执行此操作并重新加载片段吗? 问题答案: 创建一个方法,该方法开始FragmentTransaction,分离片段,然后提交
本文向大家介绍android-fragments 添加片段,包括了android-fragments 添加片段的使用技巧和注意事项,需要的朋友参考一下 示例 静态添加片段 文件:activity_main.xml 文件:fragment1.xml 文件:fragment2.xml 文件:MainActivity.java 文件:Fragment1.java 文件:Fragment2.java 动态
我可以将谷歌地图加载到活动中的Android片段中。这一直运行良好。 但现在我想使用ViewPager在视图之间导航(class
在为客户端启动新应用程序时,我在再次问自己关于谁应该负责加载数据的同一个问题:活动还是片段。我已经为不同的应用程序采取了这两种选择,我想知道哪种模式是最好的,根据您的意见: 限制代码复杂性。 处理边缘情况(如屏幕旋转、屏幕运行省电、连接丢失等) 这允许有一些片段,这些片段只是被提供给一堆对象来显示。他们对加载数据和我们如何加载数据一无所知。 另一方面,活动使用所需的任何方法加载数据(例如,最初加载
我使用的是支持片段,在片段中我设置了setRetainInstance(true)。我了解到,如果我们在片段中设置了setRetainInstance(true),那么在配置更改时不会调用片段的onCreate()和onDestroy()。但当我在samsung note3中更改字体样式时,仍然会重新创建活动,并调用fragment的onCreate()。这是配置更改吗?如果是,为什么片段实例被初