在标签切换时保存片段状态

3

我尝试了一个星期来解决这个问题,但没有成功。请帮帮我。

我使用了带有ViewPager的标签导航。这是我放置标签和FragmentPagerAdapter类的类:

 public class Detail extends SherlockFragmentActivity {

    ViewPager  mViewPager;

    TabsAdapter mTabsAdapter;


    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        setContentView(R.layout.activity_main);

     ...



     ActionBar bar = getSupportActionBar();
     bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
     bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

     mViewPager = (ViewPager)findViewById(R.id.pager);

     // Add the tabs
     mTabsAdapter = new TabsAdapter(this, bar, mViewPager);
     mTabsAdapter.addTab(bar.newTab().setText(R.string.filmtab),
             FragmentFilm.class, null);
     mTabsAdapter.addTab(bar.newTab().setText(R.string.cinematab),
             FragmentCinema.class, null);
     mTabsAdapter.addTab(bar.newTab().setText(R.string.dintornitab),
             FragmentPdi.class, null);



     if (savedInstanceState != null) {
         bar.setSelectedNavigationItem(savedInstanceState.getInt("tab"));
     }



    }


     @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
        }


     public static class TabsAdapter extends FragmentPagerAdapter
     implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
         private final Context mContext;
         private final ActionBar mBar;
         private final ViewPager mViewPager;
         private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

         static final class TabInfo {
             private final Class<?> clss;
             private final Bundle args;

             TabInfo(Class<?> _class, Bundle _args) {
                 clss = _class;
                 args = _args;
             }
         }

         public TabsAdapter(Detail activity, ActionBar bar, ViewPager pager) {
             super(activity.getSupportFragmentManager());
             mContext = activity;
             mBar = bar;
             mViewPager = pager;
             mViewPager.setAdapter(this);
             mViewPager.setOnPageChangeListener(this);
         }

         public void addTab(ActionBar.Tab tab, Class<? extends Fragment> clss, Bundle args) {
             TabInfo info = new TabInfo(clss, args);
             tab.setTag(info);
             tab.setTabListener(this);
             mTabs.add(info);
             mBar.addTab(tab);
             notifyDataSetChanged();
         }

         @Override
         public int getCount() {
             return mTabs.size();
         }

         @Override
         public Fragment getItem(int position) {
             TabInfo info = mTabs.get(position);
             return Fragment.instantiate(mContext, info.clss.getName(), info.args);
         }

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

         @Override
         public void onPageSelected(int position) {
             mBar.setSelectedNavigationItem(position);
         }

         @Override
         public void onPageScrollStateChanged(int state) {
         }

         @Override
         public void onTabSelected(Tab tab, FragmentTransaction ft) {
             Object tag = tab.getTag();
             for (int i=0; i<mTabs.size(); i++) {
                 if (mTabs.get(i) == tag) {
                     mViewPager.setCurrentItem(i);
                 }
             }
         }

         @Override
         public void onTabUnselected(Tab tab, FragmentTransaction ft) {

         }

         @Override
         public void onTabReselected(Tab tab, FragmentTransaction ft) {

         }
     }
}

这里有3个片段类,它们都是相同的,我只复制了一个; 在片段类中,我使用异步任务来下载我需要放入视图中的数据,我是在onActivityCreated方法中实现的:

public class FragmentFilm extends SherlockFragment
{

    private Detail act;

    private DetailedRec detail_film;
    private View view;
    private String a;




    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {



        setRetainInstance(true);
        view = inflater.inflate(R.layout.tab_film_info, container, false);

        return view;
    }

    /*
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);


    }*/


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        act =  (Detail) getActivity();


    }




    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        new DownloadFilmDetailAsyncTask().execute();


    }



    private class DownloadFilmDetailAsyncTask extends AsyncTask<Void, DetailedRec, Void>
    {

        @Override
        protected void onPreExecute() {

            super.onPreExecute();


        }

        @Override
        protected void onPostExecute(Void result) {

            super.onPostExecute(result);

            ProgressBar prBar = (ProgressBar)getView().findViewById(R.id.progressbar_film);
            prBar.setVisibility(View.GONE);
            ScrollView lay = (ScrollView)getView().findViewById(R.id.tab_filmsummary);
            lay.setVisibility(View.VISIBLE);


        }

        @Override
        protected Void doInBackground(Void... params)
        {
            try
            {


                String locale = getResources().getConfiguration().locale.getDisplayName();


                JSONObject objSend = new JSONObject();
                objSend.put("idFilm", act.getIdFilm());
                objSend.put("cinemaId",act.getIdCinema());
                int ind = locale.indexOf("(");
                String locale_send = locale.substring(0, ind-1);
                objSend.put("locale", locale_send);
                ArrayList<String> otherCin = new ArrayList<String>(Arrays.asList(act.getOtherCinemas()));
                JSONArray othCin = new JSONArray(otherCin);
                objSend.put("otherCinemas", othCin );
                JSONObject jsonObject = sendAndGetJSONObject(JSON_SERVER+"JsonServer?op=getFilmbyId",objSend);



                DetailedRec detail_rec = new DetailedRec();
                //FILM
                detail_rec.setFilmId(jsonObject.getString("filmId"));
                detail_rec.setName(jsonObject.getString("name"));
                detail_rec.setImageUrl(jsonObject.getString("imageUrl").replace("640", "80"));
                detail_rec.setActors(jsonObject.getString("actors"));
                detail_rec.setGenre(jsonObject.getString("genre"));
                detail_rec.setDirector(jsonObject.getString("director"));
                detail_rec.setPlot(jsonObject.getString("plot"));
                detail_rec.setYear(jsonObject.getString("year"));
                detail_rec.setDuration(jsonObject.getString("duration"));
                detail_rec.setTrailer(jsonObject.getString("trailer"));
                detail_rec.setRating(jsonObject.getString("rating"));

                detail_film = detail_rec;
                publishProgress(detail_rec);


            }
            catch (IOException ignored)
            {
            }
            catch (JSONException ignored)
            {
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(DetailedRec... values)
        {
            for (final DetailedRec detail_rec : values)
            {

                updateViews(detail_rec);

            }

        }

        private  JSONObject getJSONObject(String url) throws IOException, MalformedURLException, JSONException
        {
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();


            InputStream in = conn.getInputStream();

            try
            {
                StringBuilder sb = new StringBuilder();
                BufferedReader r = new BufferedReader(new InputStreamReader(new DoneHandlerInputStream(in),"WINDOWS_1252"));
                for (String line = r.readLine(); line != null; line = r.readLine())
                {
                    sb.append(line);
                }
                return new JSONObject(sb.toString());
            }
            finally
            {
                in.close();
            }
        }


        private  JSONObject sendAndGetJSONObject(String url,JSONObject request) throws IOException, MalformedURLException, JSONException
        {

            HttpClient client = new DefaultHttpClient();
            HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); //Timeout Limit
            InputStream in=null;
            try{
                 HttpPost post = new HttpPost(url);
                 StringEntity se = new StringEntity(request.toString());  
                 se.setContentType((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
                 post.setEntity(se);
                 HttpResponse response = client.execute(post);
                 HttpEntity entity = response.getEntity();
                 in = entity.getContent();
                 StringBuilder sb = new StringBuilder();
                 BufferedReader r = new BufferedReader(new InputStreamReader(new DoneHandlerInputStream(in),"WINDOWS_1252"));
                 for (String line = r.readLine(); line != null; line = r.readLine())
                 {
                    sb.append(line);
                 }
                 return new JSONObject(sb.toString());
            }catch(Exception e){

            }
            finally
            {
                in.close();
            }

            return null;

        }


    }

    private void updateViews(final DetailedRec detail_rec){
        //FILM
        TextView filmName = (TextView) getView().findViewById(R.id.movieTitle);
        filmName.setText(detail_rec.getName().trim());
        TextView actors = (TextView) getView().findViewById(R.id.movieActor);
        actors.setText(detail_rec.getActors().trim());
        TextView genre = (TextView) getView().findViewById(R.id.movieGenre);
        genre.setText(detail_rec.getGenre().trim());
        TextView director = (TextView) getView().findViewById(R.id.movieDirector);
        director.setText(detail_rec.getDirector().trim());
        TextView plot = (TextView) getView().findViewById(R.id.moviePlot);
        plot.setText(detail_rec.getPlot().trim());
        TextView year = (TextView) getView().findViewById(R.id.movieYear);
        year.setText(detail_rec.getYear().trim());
        TextView duration = (TextView) getView().findViewById(R.id.movieDuration);
        duration.setText(detail_rec.getDuration().trim());
        ImageView image = (ImageView) getView().findViewById(R.id.moviePoster);

        new DownloadImagesTask(detail_rec.getImageUrl().trim().replace("80", "100")).execute(image);
        //image.setImageBitmap(downloadBitmap(detail_rec.getImageUrl().trim().replace("80", "100")));
        //Rating
        if(detail_rec.getRating().compareTo("N/A")!=0){
            RatingBar rateBar = (RatingBar)getView().findViewById(R.id.MovieRatingBar);
            rateBar.setRating(Float.parseFloat(detail_rec.getRating()));
        }
        //Trailer 
        Button trailer = (Button)getView().findViewById(R.id.trailer);
        if(detail_rec.getTrailer().compareTo("")!=0){
            trailer.setVisibility(View.VISIBLE);
            trailer.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    int index = detail_rec.getTrailer().indexOf("v=");
                    String videoId="";
                    if(index!=-1){
                        videoId = detail_rec.getTrailer().substring(index+2); //"Fee5vbFLYM4";
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:"+videoId)); 
                        intent.putExtra("VIDEO_ID", videoId); 
                        startActivity(intent); 
                    }


                }
            });
        }

    }

}

好的,我的应用程序中我希望片段只加载一次。我解释得很清楚: 当我启动详细类时,片段类被实例化并且所有3个片段中的AsyncTask都开始了。现在当用户从一个选项卡切换到另一个选项卡时,我希望未选择的选项卡中的片段不会丢失数据和视图,因为现在当我从一个选项卡切换到另一个选项卡,然后返回第一个选项卡,这会重新创建,并再次调用onActivityCreated方法!

请帮助我,我在所有地方都搜索了但是我找不到解决方案!!

P.S. 我使用SherlockActionBar,我不知道它是否相关。对我的糟糕英语表示抱歉

谢谢

1个回答

11

在实例化ViewPager之后,添加以下内容

mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(3);

应该就这样了!


虽然这将解决问题,但它实际上并没有通过 Bundle 保存状态。 - Kevin Mark
对我来说非常好用,避免了在简单的片段代码中编写保存实例状态方法的代码。 - Piyush-Ask Any Difference
哦,终于了。这么简单。我一直在尝试各种涉及状态和捆绑包的其他答案,但都不太行,而这就是它所需要的! - AndrWeisR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接