我正在使用Manishkpr上的教程来创建一个应用程序,您可以在其中滑动1)layoutOne:在这里您创建一个文件和2)layoutTwo:显示某个文件夹中所有已创建文件的列表视图。
问题:如果您创建了一个文件,它不会立即显示在列表视图中。我发现我应该在LayoutOne.java中使用这段代码:
LayoutTwo fragment = (LayoutTwo) getFragmentManager().findFragmentByTag("TESTTWO");
fragment.getAdapter().notifyDataSetChanged();
在LayoutTwo.java中,我添加了:
private static final String TAG = "TESTTWO";
//and the function getAdapter:
public CustomArrayAdapter getAdapter() {
return adapter;
}
但是,我在fragment.getAdapter().notifyDataSetChanged();
上获得了一个nullpointer异常。我怎么能解决这个问题,这实际上是最好的方法吗?
修改
myList = new ArrayList<RecordedFile>();
File directory = Environment.getExternalStorageDirectory();
file = new File(directory + "/test/");
File list[] = file.listFiles();
for (int i = 0; i < list.length; i++) {
if (checkExtension(list[i].getName()) == true) {
RecordedFile q = new RecordedFile();
q.setTitle(list[i].getName());
q.setFileSize(readableFileSize(list[i].length()));
myList.add(q);
}
}
adapter = new CustomArrayAdapter(myContext,
R.layout.listview_item_row, myList);
listView.setAdapter(adapter);
答案 0 :(得分:8)
我正在使用Manishkpr上的教程创建一个可以滑动的应用程序 1)layoutOne:在这里你创建一个文件和2)layoutTwo:显示一个 列表查看某个文件夹中所有已创建的文件。
问题:如果您创建了一个文件,它不会立即显示在文件中 列表视图。
如果您只有两个布局可以滑动,这意味着两个布局都会在内存中显示并可供访问。然后,您可以为ListView
分配一个ID,当需要刷新数据时,只需查找ListView
中的Activity
,获取其适配器并对其进行更新,如下所示:< / p>
ListView list = (ListView) getActivity().findViewById(R.id.theIdOfTheList);
((BaseAdapter)list.getAdapter()).notifyDataSetChanged();
无论你是否在适配器上调用notifyDataSetChanged()
,ListView都不会更新,因为它没有看到新文件,从它的角度看,数据集是完整的。根据适配器的外观,您有两种选择:
重建ListView
的数据,基本上重做首次构建ListView
时的操作:检查该目录并重新列出所有文件。
// create the new file
File directory = Environment.getExternalStorageDirectory();
file = new File(directory + "/test/");
File list[] = file.listFiles();
ListView list = (ListView) getActivity().findViewById(R.id.theIdOfTheList);
// I'm assuming your adapter extends ArrayAdapter(?!?)
CustomArrayAdapter caa = (CustomArrayAdapter) list.getAdapter();
caa.clear();
for (int i = 0; i < list.length; i++) {
if (checkExtension(list[i].getName())) {
RecordedFile q = new RecordedFile();
q.setTitle(list[i].getName());
q.setFileSize(readableFileSize(list[i].length()));
caa.add(q);
}
}
或者您可以为新创建的文件手动创建RecordFile
对象,并将其添加到现有适配器:
ListView list = (ListView) getActivity().findViewById(R.id.theIdOfTheList);
(CustomArrayAdapter) caa = (CustomArrayAdapter) list.getAdapter();
File newFile = new File("directory" + "/test/theNewFileName.extension");
RecordFile rf = new RecordFile();
rf.setTitle(newFile.getName());
rf.setFileSize(readableFileSize(newFile.length()));
// have a method to return a reference of the data list(or a method
// to add the data directly in the adapter)
List<RecordFile> data = caa.getListData();
data.add(rf);
caa.notifyDataSetChanged();
我不知道你的适配器是怎么样的,所以试试我说的,如果它不起作用,请发布适配器的代码。
答案 1 :(得分:1)
我认为这是因为viewpager加载了layoutTwo,但是你没有使用notifyDataSetChanged刷新它。你只刷新LayoutTwo的数据,但它没有刷新,因为viewpager有一个方法:pager.setOffscreenPageLimit(1);
AFAIK这是默认的,所以接下来会发生在行中:加载LayoutOne,加载LayoutTwo,做layoutOne中的东西,在layoutTwo中做的事情。但正如你所看到的,之后将没有负载布局。
我有一个非常类似的问题,它是一种解决方法,但重新启动了行为(和pager.removeAllViews();
)并且它运行良好而不会打扰用户。
但是要确定这会导致问题,请将其放在代码中以获取按钮clicklistener:
viewPager.removeAllViews();
finish();
startActivity(new Intent(MyActivity.this, MyActivity.class));
这不能完全解决你的问题,但是你可以看到layoutTwo是否变形,找出问题的原因。
答案 2 :(得分:1)
不久前项目中的问题几乎相同。
解决方案是将Observer模式添加到应用程序中。
查看有关该问题的官方文档:
http://developer.android.com/training/basics/fragments/communicating.html
您所注册的是Fragments
注册Activity
与Fragments
的{{1}}。每当Fragment
一个callback
发生变化时,您就Activity
向message
提出Fragments
,ListView
将会采取行动并将Fragment
传递给另一个{{1}}。< / p>
然后,您可以获取特定{{1}}的{{1}}并更新它或您想要做的任何事情。
它非常简单和强大; - )
答案 3 :(得分:0)
嗨,也许它有点晚了,但我很难做到这一点,这就是我设法做到的方式。
这绝对不是最好的方法,但它正在发挥作用。
在开始时初始化你的片段,这样我们就可以保存它们的每个实例,然后选择是否要实例化它们。
ExampleFragment searchFragment = null;
ExampleFragment fileListFragment = null;
现在将FragmentStatePagerAdapter
更改为以下内容,以便我们使用之前初始化的片段
ExampleFragment searchFragment = null;
ExampleFragment fileListFragment = null;
现在在PagerAdapter
班级:
class pagerAdapter extends FragmentStatePagerAdapter
{
public pagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class
// below).
switch (position) {
case 0:
if (searchFragment != null) {
return searchFragment;
}
return searchFragment = new ExampleFragment();
case 1:
if (downFragment != null) {
return downFragment;
}
return downFragment = new ExampleFragment();
}
return null;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
}
return null;
}
}
通过这种方式,我们可以调用每个片段中的方法,并从Main Activity
与它们进行通信,而不会出现任何视图或上下文问题。
然后在操作栏的onTabSelected
方法或任何其他类似"onChangeTab"
的方法中,您只需重置从您的片段中调用所需的方法。
@Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
if ((tab.getPosition()) == 1) {
downFragment.yourMethod();
}
mViewPager.setCurrentItem(tab.getPosition());
}
它并不优雅,但却像魅力一样。