3

故事是在ViewPager中有五個片段,每個片段在ViewPager上出現時必須運行一個AsyncTask。我正在嘗試與正確答案here完全相同。我把AsyncTask放在onResumeFragment,它工作正常。但是,在AsyncTask成功運行後更新視圖時,問題就開始了。因爲當我更新數據集時,我在onCreateView中創建的視圖(RecyclerView)爲null。我也在onActivityCreated內試過setRetainInstance(true)。它沒有工作。如何在恢復片段時維護在ViewPager中片段的onCreateView中創建的視圖實例?

這裏是我的代碼,

MainActivity.java

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    //Tab & Pager 

    viewPager = (ViewPager) findViewById(R.id.main_tab_content); 
    adapter = new ViewPagerAdapter(getSupportFragmentManager()); 
    viewPager.setAdapter(adapter); 
    addPagerListener(); 
} 

private void addPagerListener(){ 
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 

     @Override 
     public void onPageSelected(int newPosition) { 
      FragmentLifecycle fragmentToShow = (FragmentLifecycle)adapter.getItem(newPosition); 
      fragmentToShow.onResumeFragment(); 

      FragmentLifecycle fragmentToHide = (FragmentLifecycle)adapter.getItem(currentPosition); 
      fragmentToHide.onPauseFragment(); 

      currentPosition = newPosition; 
     } 

     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 

     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 

     } 
    }); 
} 

class ViewPagerAdapter extends FragmentPagerAdapter { 
    public ViewPagerAdapter(FragmentManager manager) { 
     super(manager); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     switch (position){ 
      case 0: return new HomeFragment(); 
      case 1: return new ArtistFragment(); 
      case 2: return new AlbumsFragment(); 
      case 3: return new CollectionsFragment(); 
      case 4: return new SavedFragments(); 
      default: return null; 
     } 
    } 

    @Override 
    public int getCount() { 
     return 5; 
    } 

} 

這裏是我的第二個片段的代碼,其餘的片段是空爲止。

public class ArtistFragment extends Fragment implements FragmentLifecycle{ 

@BindView(R.id.recyclerview_frag_artist) 
RecyclerView mRecyclerView; 

RecyclerView.Adapter mAdapter; 
RecyclerView.LayoutManager mLayoutManager; 

@BindView(R.id.radioBtnAll_frag_artist) 
RadioButton radioAll; 

@BindView(R.id.radioBtnMale_frag_artist) 
RadioButton radioMale; 

@BindView(R.id.radioBtnFemale_frag_artist) 
RadioButton radioFemale; 

ArrayList<String> vocalistNameList; 
Context context; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View rootView = inflater.inflate(R.layout.fragment_artists, container, false); 
    ButterKnife.bind(this, rootView); 
    mRecyclerView.setHasFixedSize(true); 
    mLayoutManager = new LinearLayoutManager(rootView.getContext()); 
    mRecyclerView.setLayoutManager(mLayoutManager); 
    vocalistNameList = getDummyDS(); 
    mAdapter = new MyListAdapter(vocalistNameList); 
    mRecyclerView.setAdapter(mAdapter); 
    radioAll.setChecked(true); 
    return rootView; 
} 

@Override 
public void onActivityCreated(@Nullable Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    setRetainInstance(true); 
} 

private ArrayList<String> getDummyDS(){ 
    ArrayList<String> dataset = new ArrayList<>(); 
    dataset.add("test"); 
    dataset.add("test"); 
    dataset.add("test"); 
    dataset.add("test"); 
    dataset.add("test"); 
    dataset.add("test"); 
    dataset.add("test"); 
    return dataset; 
} 

private void getVocalistList(Gender gender){ 
    RequestParams params = new RequestParams(); 
    params.put("action","query"); 
    params.put("list","allcategories"); 
    params.put("acprefix","Vocalist-"); 
    params.put("format","json"); 
    params.put("aclimit","5000"); 

    MyRestClient.get("", params, new JsonHttpResponseHandler(){ 
     ProgressDialog progress; 
     @Override 
     public void onStart() { 
      progress = ProgressDialog.show(AppConstants.activity, "Please wait", 
         "Loading data..", true); 
      progress.setCancelable(true); 
     } 

     @Override 
     public void onSuccess(int statusCode, Header[] headers, JSONObject response) { 
      progress.dismiss(); 
      vocalistNameList = new ArrayList<String>(); 
      try { 
       JSONArray vocalListJsonArray = response.getJSONObject("query").getJSONArray("allcategories"); 
       for(int i=0; i<vocalListJsonArray.length(); i++){ 
        String vocalListName = vocalListJsonArray.getJSONObject(i).getString("*").replace("Vocalist-",""); 
        vocalistNameList.add(vocalListName); 
       } 
       mAdapter = new MyListAdapter(vocalistNameList); 
       mRecyclerView.setAdapter(mAdapter); // <= RecyclerView is null and app is crashing 
       mAdapter.notifyDataSetChanged(); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
     } 

     @Override 
     public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { 
      progress.dismiss(); 
      Log.i("failure", "failed "+statusCode); 
     } 
    }); 
} 

@Override 
public void onPauseFragment() { 
    Toast.makeText(AppConstants.applicationContext, "onPauseFragment():", Toast.LENGTH_SHORT).show(); 
} 

@Override 
public void onResumeFragment() { 
    getVocalistList(Gender.All); 
    Toast.makeText(AppConstants.applicationContext, "onResumeFragment(): Artist", Toast.LENGTH_SHORT).show(); 
} 

自從一週前我一直在試圖解決這個問題。任何想法? (P.S我使用Android Asynchronous Http Client代替AsyncTask

回答

1

你必須做這樣的事情:

pager.setOffscreenPageLimit([quantity of tabs that you would like to keep in memory]); 

看看這個答案。 ViewPager inside Fragment loses content when returning to it

+0

我認爲它可以正常工作,只有很少的片段。我的只有5個,但我想要一個解決方案供將來使用。 –

+0

另外,它沒有工作兄弟。 –

1

最後我得到了解決方案。這很簡單。

  1. 我刪除了接口FragmentLifecycle的實現。
  2. 向每個片段添加以下方法。

    @Override 
    public void setUserVisibleHint(boolean isVisibleToUser) { 
        super.setUserVisibleHint(isVisibleToUser); 
        if(isVisibleToUser && !isDataLoaded){ 
         getVocalistList(Gender.All); 
         isDataLoaded = true; 
        } 
    } 
    

它的工作原理像變魔術一樣。我不需要擔心丟失RecyclerView實例,因爲當調用setUserVisibleHint方法時它不爲空。

+1

好吧,我不太相信這是「非常簡單」,但感謝您的調查結果......我使用ButterKnife,並且看到我的RecyclerView正在被解僱,並且每當我返回時都會創建一個新的RecyclerView到ViewPager內部的片段...我在哪裏可以找到'FragmentLifecycle'界面?還有,爲什麼在AsyncTask完成加載數據之前將isDataLoaded標誌設置爲true? – rexxar

+1

對不起,我遲到了,在這裏,你去。 http://stackoverflow.com/a/24386516/1976608 –

相關問題