我对Android相对较新,我对列表,片段以及存储某些状态数据的位置有一些疑问。 我正在一个例子中,我有一个列表视图和一个使用片段的详细视图。 当我第一次打开应用程序时,我加载(从Web服务)项目列表(使用asyntask)。 我想“保存”该列表,所以如果我需要回到这个活动(列表),我不需要再次执行asynctask。 哪个是“保存”此列表的更好地方? Application对象是个好地方吗?
然后,当我单击列表中的项目时,我想打开一个新活动并从该对象加载详细数据。 将该对象传递给详细活动的最佳方法是什么? 使用Application对象并从列表中获取所选项(例如,使用onItemSelectedListener中的位置参数)(如果我有一个包含应用程序对象中项目的列表)? 让我的“Item”对象实现Parcelable接口并在意图中传递整个对象? 还有其他想法吗?
谢谢,对不起我的英语。
答案 0 :(得分:1)
如果您想保持良好的数据,SQLite是正确的选择。
如果您想暂时缓存数据,那么savedInstanceState Bundle就在这里。我向您展示了使用Fragment和ListView的示例。
public static final String BUNDLE_CACHE = "ListFragment.BUNDLE_CACHE";
private ArrayList<ListItem> mCachedData;
private ListView mListView;
private ListItemAdapter mListAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((savedInstanceState != null) && savedInstanceState.containsKey(BUNDLE_CACHE)) {
this.mCachedData = savedInstanceState.getParcelableArrayList(BUNDLE_CACHE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
LinearLayout layout = (LinearLayout) inflater.inflate(
R.layout.layout_fragment, null);
this.mListAdapter = new ListAdapter(inflater.getContext(),
R.layout.item_list_topic_categories);
this.mListView = (ListView) layout.findViewById(R.id.listView);
this.mListView.setAdapter(this.mListAdapter);
this.mListView.setOnItemClickListener(this.mItemClickListener);
if (this.mCachedData == null) {
Log.d("onCreateView", "I make the request");
this.downloadData();
... // After download is finished, you put somewhere:
this.mCachedData = downloadedData;
} else {
Log.d("onCreateView", "Cool, the data is cached");
this.buildList(this.mCachedData);
}
return layout;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// You put the content of your list, which is this.mCachedData, in the state
outState.getParcelableArrayList(BUNDLE_CACHE, this.mCachedData);
}
我也在我的一些应用程序上使用webservices,而且当我在片段之间切换视图时,savedInstanceState对于不再执行webservice调用非常有用。 当片段视图被销毁但片段仍然存在时,将应用此案例。当再次创建视图时,它将使用缓存的数据,而不是从webservices再次下载。
要将Parcelable发送到活动中的片段(根据biovamp的示例),您可以使用:
Bundle args = new Bundle();
args.putParcelable("keyName", parcelableObject);
fragment.setArguments(args);
在您的片段中,您可以使用它来获取您的Parcelable:
this.getArguments().getParcelable("keyName");
要创建Parcelable,请参阅本教程,例如:http://techdroid.kbeanie.com/2010/06/parcelable-how-to-do-that-in-android.html
现在,你说:
然后,当我点击列表中的项目时,我想打开一个新活动
因此,如果您仍想从ListFragment创建DetailsActivity,则使用Intent发送数据:
ListItem item = ... // get your item data
intent.putExtra("keyItem", item);
使用以下命令将其放入新创建的DetailsActivity中:
Bundle extras = getIntent().getExtras();
if (extras !=null) {
ListItem value = (ListItem) extras.getParcelable("keyItem");
}
答案 1 :(得分:0)
您应该将列表保存在任何持久存储中(并且Application不是持久存储)。 SQLite数据库最适合您的情况。
不是创建新的Activity,而是创建新的Fragment,将其添加到activity,然后使用所需的对象作为参数调用一些(自定义)函数(例如loadMyItem()
)。通过这种方式,它不需要在Intent中看起来更具可读性(以及今天推荐的方式)
示例强>
主要的想法是,当您在SectionsFragment
上执行某项操作(例如,点击ListView的项目)时,它会调用它的父Activity
,并且它Activity
决定应加载的内容和位置。在此示例中,Activity
调用DetailFragment
来加载其中的一些数据。
您的活动课程:
public class MainActivity extends Activity{
private DetailFragment mDetailFragment;
private SectionsFragment mSectionsFragment;
/*initialization stuff, it's not interesting now*/
//Section is just custom class for example - it can be whatever you want
public void setSection(Section section){
mDetailFragment.loadSection(section);
}
}
你的SectionsFragment:
public class SectionsFragment extends Fragment{
/*initialization is also skipped*/
/**This method may be called when ListView's item is touched or somwhere else - it's doesn't matter*/
private void setSection(Section section){
if(!(getActivity() instanceof MainActivity))
throw new ClassCastException("This fragment can be created only by MainActivity");
MainActivity activity = (MainActivity) getActivity();
activity.setSection(section);
}
}
你的DetailFragment:
public class DetailFragment extends Fragment{
/*initialization*/
public void loadSection(Section section){
//Here your fragment decides what exactly it should load
//for this section. Maybe do some networking, or load data from database
//whatever you want
}
}