求助:ViewPager中3个ListFragment内容无法显示问题
我开发了一个带有ViewPager的Android应用,需要展示4个标签页,其中3个为ListFragment。但运行应用时,这3个ListFragment显示为空。以下是我的相关代码:
MainActivity.java
package com.hwdeveloper.bitsandpizzas; import android.content.Context; import android.content.Intent; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.MenuItemCompat; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.ShareActionProvider; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; public class MainActivity extends AppCompatActivity { private ShareActionProvider shareActionProvider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); SectionsPagerAdapter pagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); viewPager.setAdapter(pagerAdapter); TabLayout tabLayout = (TabLayout)findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); } @Override public View onCreateView(String name, Context context, AttributeSet attrs) { return super.onCreateView(name, context, attrs); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); MenuItem menuItem = menu.findItem(R.id.action_share); shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem); setShareActionProvider("Want join me for Pizza?"); return super.onCreateOptionsMenu(menu); } public void setShareActionProvider(String text) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("Text/Plain"); intent.putExtra(Intent.EXTRA_TEXT, text); shareActionProvider.setShareIntent(intent); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_create_order: Intent intent = new Intent(this, OrderActivity.class); startActivity(intent); return true; default: return super.onOptionsItemSelected(item); } } }
SectionsPagerAdapter.java
public class SectionsPagerAdapter extends FragmentPagerAdapter { SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return 4; } @Override public int getItemPosition(@NonNull Object object) { return PagerAdapter.POSITION_NONE; } @Nullable @Override public CharSequence getPageTitle(int position) { switch (position){ case 0: return "Home"; case 1: return "Pizza"; case 2: return "Pasta"; case 3: return "Stores"; } return super.getPageTitle(position); } @Override public Fragment getItem(int position) { switch (position) { case 0: return new TopFragment(); case 1: return new PizzaFragment(); case 2: return new PastaFragment(); case 3: return new StoresFragment(); default: return null; } } }
TopFragment.java
public class TopFragment extends Fragment { public TopFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_top, container, false); } }
PizzaFragment.java
public class PizzaFragment extends ListFragment { public PizzaFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ArrayAdapter<String> adapter = new ArrayAdapter<>(inflater.getContext(),android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.pizzas)); setListAdapter(adapter); return super.onCreateView(inflater, container, savedInstanceState); } }
PastaFragment.java
public class PastaFragment extends ListFragment { public PastaFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ArrayAdapter<String> adapter = new ArrayAdapter<>(inflater.getContext(), android.R.layout.simple_list_item_1,getResources().getStringArray(R.array.pasta)); setListAdapter(adapter); return super.onCreateView(inflater, container, savedInstanceState); } }
StoresFragment(代码不完整)
问题排查与修复方案
我帮你看了下代码,ListFragment显示为空主要是因为适配器初始化的时机不对,还有几个细节需要确认,具体修复步骤如下:
1. 调整ListFragment的适配器初始化位置
onCreateView方法是用来创建Fragment视图的,此时ListView还没完全绑定到Fragment的生命周期里,直接在这里调用setListAdapter大概率不会生效。正确的做法是把适配器的初始化代码移到onActivityCreated方法中——这个方法会在Fragment成功附加到Activity、视图层级完全创建后执行,此时设置适配器才能确保ListView能正确接收数据。
修改PizzaFragment.java:
public class PizzaFragment extends ListFragment { public PizzaFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 直接返回ListFragment的默认视图即可 return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // 在这里初始化并设置适配器 ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.pizzas)); setListAdapter(adapter); } }
同样的,把PastaFragment.java改成下面这样:
public class PastaFragment extends ListFragment { public PastaFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.pasta)); setListAdapter(adapter); } }
2. 确认字符串数组资源存在
检查你项目里的res/values/strings.xml文件,确保已经正确定义了pizzas和pasta这两个字符串数组,示例如下:
<string-array name="pizzas"> <item>玛格丽特披萨</item> <item>意大利辣香肠披萨</item> <item>夏威夷披萨</item> </string-array> <string-array name="pasta"> <item>培根蛋酱意面</item> <item>阿尔弗雷多奶油意面</item> <item>香辣通心粉</item> </string-array>
如果这些数组不存在,getResources().getStringArray()会返回null,适配器没有数据,列表自然就显示为空了。
3. 完善StoresFragment的实现
因为你提到StoresFragment代码不完整,如果它也是ListFragment的话,按照上面的方式完成初始化逻辑即可——确保在onActivityCreated里设置适配器和数据。
做完这些修改后,重新运行应用,你的三个ListFragment应该就能正常显示数据了。
内容的提问来源于stack exchange,提问作者it4Astuces

