我已经从TabbedActivity
模板(在Android Studio中)创建了活动:
此模板使用Fragment
和FragmentPagerAdapter
来处理标签
这是两个类的代码,PlaceholderFragment extends Fragment
和SectionsPagerAdapter extends FragmentPagerAdapter
:
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_view, container, false);
int scnum = getArguments().getInt(ARG_SECTION_NUMBER);
final ListView listView = (ListView) rootView.findViewById(R.id.products_list);
// here refresh my listView trough internet
return rootView;
}
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(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).
return PlaceholderFragment.newInstance(position + 1);
}
@Override
public int getCount() {
// Show 3 total pages.
return 3;
}
}
在onCreateView
方法中,我刷新ListView
。切换标签时会调用此方法
但是我需要在用户切换标签时刷新ListView
,但是:
1.每10秒
2.当用户返回此活动时(调用onRestart()
方法)
我不知道如何访问我的ListView
onCreateView
外onCreateView
方法
我已经尝试过许多来自互联网的解决方案,从onRestart
方法调用ListView
方法,只是从onRestart()
访问我的SectionsPagerAdapter
。他们都没有工作。
在全局的Activity类中,我有一个ViewPager
和private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
的实例:
onCreate
他们通过这种方式在 mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
中被初始化:
onCreateView
我认为,有两种可能的解决方案,访问我的片段视图或只记得@Override
protected void onRestart() {
super.onRestart();
mSectionsPagerAdapter.notifyDataSetChanged();
}
。
我已经尝试过:
这个不起作用:
@Override
protected void onRestart() {
super.onRestart();
Fragment f = mSectionsPagerAdapter.getItem(0); // tab with my list view is first tab. ( getItem(1) also does not work )
View v = f.getView(); // v is null here, however f isn't.
final ListView listView = v.findViewById(R.id.products_list); // v is null, NullPointerException is thrown.
// here refresh my listView trough internet
}
由于NullPointerException,这个应用程序崩溃:
int layerLen[] = {0};
修改:
自从我开始使用Kotlin以来,基于该语言的答案也将被接受。但是,我是Kotlin的新手,因此需要更详细的答案。
答案 0 :(得分:2)
因此,您在ViewPager中的片段中有一个列表。有几种方法可以解决你的问题,我建议你使用第一种,因为它是最简单的。
片段具有生命周期回调,这些回调与包含该片段的Activity的生命周期回调一起触发。它涵盖了大多数方法,但遗憾的是不是您正在寻找的onRestart
。但这不是一个大问题。实际上,您几乎不需要onRestart
,因为您拥有onStart
方法,可以从Fragments和Activities访问该方法。每次重新启动活动+第一次启动活动时都会调用它。正如我们所看到的,它正是您所需要的。因此,要每次更新列表,只需从onCreate
方法中删除更新代码,然后将其放入片段的onStart
方法中。
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
private ListView listView = null;
public PlaceholderFragment() {
}
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_view, container, false);
int scnum = getArguments().getInt(ARG_SECTION_NUMBER);
listView = (ListView) rootView.findViewById(R.id.products_list);
return rootView;
}
@Override
public void onStart() {
// here refresh your listView trough internet using the listView class field
}
}
另一种选择是在活动中获取对片段的引用。我通常使用的解决方案是保留对适配器内部片段的引用。它类似于您问题中的第二个选项。解决方案的唯一问题是mSectionsPagerAdapter.getItem(0);
总是创建一个新片段,而您需要获取对已存在片段的引用。
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private PlaceholderFragment fragmentZero = null;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
PlaceholderFragment tabFragment = PlaceholderFragment.newInstance(position + 1);
if (position == 0) {
fragmentZero = tabFragment;
}
return tabFragment;
}
@Override
public int getCount() {
return 3;
}
public PlaceholderFragment getFragmentZero() {
return fragmentZero;
}
}
您还需要将列表更新逻辑移动到PlaceholderFragment中的单独方法:
private ListView listView = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_view, container, false);
int scnum = getArguments().getInt(ARG_SECTION_NUMBER);
listView = (ListView) rootView.findViewById(R.id.products_list);
refreshListView();
return rootView;
}
public void refreshListView() {
// here refresh your listView trough internet
}
此时你可以这样做:
@Override
protected void onRestart() {
super.onRestart();
Fragment listFragment = mSectionsPagerAdapter.getFragmentZero();
listFragment.refreshListView();
}
每当活动中有一个片段时,无论是否在ViewPager中,您都可以使用FragmentManager获取对该片段的引用。有关ViewPager选项的详细信息,请查看this。
上面的所有代码都相当简单,如果您更愿意在Kotlin中实现它,则不需要任何特殊的Kotlin习语。你可以从在android studio中转换你的类开始。要做到这一点:
Control + Shift + A
或在Mac上按Command + Shift + A
Convert Java File to Kotlin File
您最好使用给定类的Kotlin代码。唯一可能与java完全不同的是处理ARG_SECTION_NUMBER
因为Kotlin没有静态字段而是使用Companion Objects。