18

Tôi có đoạn mã sau:Android làm thế nào để ngăn chặn làm mới Những mảnh vỡ về biến đổi tab

MainActivity.java

package com.erc.library; 

import java.io.BufferedInputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.net.URL; 
import java.net.URLConnection; 

import android.app.ActionBar; 
import android.app.ActionBar.Tab; 
import android.app.FragmentTransaction; 
import android.content.SharedPreferences; 
import android.content.res.Resources; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.os.Environment; 
import android.os.StrictMode; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.view.ViewPager; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.widget.TextView; 
import android.widget.Toast; 

import com.erc.sayeghlibrary.adapter.TabsPagerAdapter; 

public class MainActivity extends FragmentActivity implements 
     ActionBar.TabListener { 

    private ViewPager viewPager; 
    private TabsPagerAdapter mAdapter; 
    private ActionBar actionBar; 
    // Tab titles 
    private String[] tabs = { "Stories", "Dictionaries", "eBooks"}; 

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






     int actionBarTitleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android"); 
     if (actionBarTitleId > 0) { 
      TextView title = (TextView) findViewById(actionBarTitleId); 
      if (title != null) { 
       title.setTextColor(Color.WHITE); 
      } 
     }  

     // Initilization 
     viewPager = (ViewPager) findViewById(R.id.pager); 
     actionBar = getActionBar(); 
     mAdapter = new TabsPagerAdapter(getSupportFragmentManager()); 

     viewPager.setAdapter(mAdapter); 
     actionBar.setHomeButtonEnabled(false); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 


     // Adding Tabs 
     for (String tab_name : tabs) { 
      actionBar.addTab(actionBar.newTab().setText(tab_name) 
        .setTabListener(this)); 
     } 

     /** 
     * on swiping the viewpager make respective tab selected 
     * */ 
     viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 

      @Override 
      public void onPageSelected(int position) { 
       // on changing the page 
       // make respected tab selected 
       actionBar.setSelectedNavigationItem(position); 
      } 

      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) { 
      } 

      @Override 
      public void onPageScrollStateChanged(int arg0) { 
      } 
     }); 







    } 

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

    @Override 
    public void onTabSelected(Tab tab, FragmentTransaction ft) { 
     // on tab selected 
     // show respected fragment view 
     viewPager.setCurrentItem(tab.getPosition()); 


    } 

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






     @Override 
     public boolean onCreateOptionsMenu(Menu menu) { 
     MenuInflater inflater = getMenuInflater(); 
     inflater.inflate(R.menu.main, menu); 
     return true; 
     } 




     @Override 
     public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
     // action with ID action_refresh was selected 
     case R.id.Favorites: 
      Toast.makeText(this, "Favorites selected", Toast.LENGTH_SHORT) 
       .show(); 
      break; 
     // action with ID action_settings was selected 

     default: 
      break; 
     } 

     return true; 
     } 


} 

TabsPagerAdapter.java

package com.erc.library.adapter; 

import com.erc.library.Dictionaries; 
import com.erc.library.Ebooks; 
import com.erc.library.Stories; 

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentPagerAdapter; 

public class TabsPagerAdapter extends FragmentPagerAdapter { 

    public TabsPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int index) { 

     switch (index) { 
     case 0: 

      return new Stories(); 
     case 1: 

      return new Dictionaries(); 
     case 2: 
      // Movies fragment activity 
      return new Ebooks(); 
     } 

     return null; 
    } 

    @Override 
    public int getCount() { 
     // get item count - equal to number of tabs 
     return 3; 
    } 

} 

Tôi đang làm ứng dụng thư viện trong đó điều hướng là theo tab, vấn đề là mỗi lần tôi chuyển từ tab thứ ba sang fi đầu tiên hoặc thứ ba đến thứ ba, nội dung tab là làm mới, tôi muốn ngăn chặn làm mới, Bất kỳ trợ giúp xin vui lòng?

+0

Ok tôi đã tìm thấy các giải pháp, tôi nên đặt dòng sau: viewPager.setOffscreenPageLimit (số lượng các tab); –

Trả lời

62

Theo mặc định, ViewPager tạo lại các đoạn khi bạn vuốt trang. Để ngăn chặn điều này, bạn có thể thử một trong hai điều sau:

1. Trong số onCreate() đoạn của bạn, hãy gọi setRetainInstance(true).

2. Nếu số lượng mảnh vỡ là cố định & tương đối nhỏ, sau đó trong bạn onCreate() thêm đoạn mã sau:

mViewPager = (ViewPager)findViewById(R.id.pager); 
mViewPager.setOffscreenPageLimit(limit);   /* limit is a fixed integer*/ 

Nếu tôi nhớ không lầm, tùy chọn thứ hai là đầy hứa hẹn hơn. Nhưng tôi mong bạn thử cả hai và xem cái nào trong số chúng hoạt động.

+1

Việc giữ lại đoạn sẽ không hoạt động trong trường hợp này và việc giữ lại thường là một hành động không tốt vì nó có thể gây khó khăn để theo dõi rò rỉ bộ nhớ khi được sử dụng mà không thận trọng. Tôi sẽ sử dụng ở đây một lựa chọn thứ hai, bởi vì bạn đang nói với ViewPager - "cache một mảnh X cho tôi". Và đó là nó – Gaskoin

+0

Vâng, như bạn đã nói, tùy chọn đầu tiên nên được sử dụng khôn ngoan ... mặc dù nó không hoạt động;) –

+0

Câu trả lời tuyệt vời .setOffScreenLimit() đã làm việc cho tôi. – JakeWilson801

1

Kể từ khi hoạt động thực hiện ActionBar.TabListener, onCreate() của hoạt động được gọi lại nhiều lần. Vì vậy, đặt đoạn mã sau vào onResume() phương pháp:

// Initilization 
    viewPager = (ViewPager) findViewById(R.id.pager); 
    actionBar = getActionBar(); 
    mAdapter = new TabsPagerAdapter(getSupportFragmentManager()); 

    viewPager.setAdapter(mAdapter); 
    actionBar.setHomeButtonEnabled(false); 
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 


    // Adding Tabs 
    for (String tab_name : tabs) { 
     actionBar.addTab(actionBar.newTab().setText(tab_name) 
       .setTabListener(this)); 
    } 

    /** 
    * on swiping the viewpager make respective tab selected 
    * */ 
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 

     @Override 
     public void onPageSelected(int position) { 
      // on changing the page 
      // make respected tab selected 
      actionBar.setSelectedNavigationItem(position); 
     } 

     @Override 
     public void onPageScrolled(int arg0, float arg1, int arg2) { 
     } 

     @Override 
     public void onPageScrollStateChanged(int arg0) { 
     } 
    }); 
16

người ta phải dụ FragmentPagerAdapter đầu tiên, sau đó .getCount() sẽ trả về một giá trị -

khi .getCount() - 1 nên được thiết lập như là giới hạn mặc định off-màn hình:

TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager()); 

/* the ViewPager requires a minimum of 1 as OffscreenPageLimit */ 
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1); 

ViewPager viewPager = (ViewPager) findViewById(R.id.pager); 
viewPager.setAdapter(adapter); 
viewPager.setOffscreenPageLimit(limit); 
+2

Bạn đã cứu mạng tôi. Nhưng chúc u giải thích thêm về phương thức 'ViewPager.setOffscreenPageLimit()'. –

+0

@SadeqShajary nó được giải thích trong tài liệu, có lẽ tốt hơn tôi có thể: https://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int) –

+0

pefect, cảm ơn bạn! –

4

bạn có thể xử lý xem giải trí bằng séc nếu xem là null hay không

public class FragmentExample extends Fragment { 

    private View rootView; 

    public FragmentExample() {} 

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

    if (rootView == null) { 

     rootView = inflater.inflate(R.layout.fragment_example_layout, container, false); 

     // Initialise your layout here 

    } else { 
     ((ViewGroup) rootView.getParent()).removeView(rootView); 
    } 

    return rootView; 
    } 
} 
0

Một chút muộn cho câu hỏi này, nhưng nhờ Y.S., đã biết cách ViewPager hoạt động. Tôi đã xây dựng một ứng dụng với 4 tab và tại bất kỳ thời điểm nào, nhận thấy rằng chỉ có hai tab đang được làm mới, mà tôi cho rằng đó là hành vi mặc định. Sau nhiều giờ điều tra, tôi hiểu rằng Android làm mới nhiều tab để mang lại hiệu suất vuốt trơn tru cho người dùng - bạn có thể nhận thấy rằng bạn đã nhấp vào tab2, nhưng android mang dữ liệu cho tab3 và giữ nó sẵn sàng.

Mặc dù hành vi này là tốt, nó có ưu và khuyết điểm của nó. Ưu điểm - bạn nhận được trải nghiệm vuốt trơn tru, không có dữ liệu được tải từ máy chủ bên ngoài khi bạn truy cập vào tab đó. Việc thực hiện backstack của bạn trong các tab có thể bị quăng. Khi bạn nhấp vào một tab, máy nhắn tin xem thực sự gọi tab mượt mà hơn và bạn sẽ gặp rắc rối lớn, nếu phương pháp của bạn đang thiết lập backarrow (nhà) ở trên cùng bên trái dựa trên những gì nằm trong backstack trong tab được nhấp.

setOffscreenPageLimit là câu trả lời cho điều này.Nếu bạn muốn khung backstack tùy chỉnh của mình hoạt động và không muốn tab3 được gọi khi tab2 được nhấp, bạn chỉ cần đặt giá trị cho số lượng tab. Ví dụ, nếu bạn có 4 tab, đặt setOffScreePageLimit (4). Điều này có nghĩa là Android sẽ làm mới tất cả 4 mảnh ban đầu, đó là một chút chi phí hiệu năng (mà bạn nên quản lý đúng cách). Tuy nhiên, backstack và chuyển đổi tab của bạn vẫn còn nguyên vẹn. Hi vọng điêu nay co ich.

2

Trong onCreate() của mảnh vỡ của bạn, hãy gọi setRetainInstance (true)

+0

thay vì gọi 'setRetainInstance (true)' người ta có thể sử dụng 'FragmentStatePagerAdapter' (nó phụ thuộc vào hành vi dự định, như tài liệu SDK đọc:" vòng đời mảnh sẽ hơi khác khi hoạt động được tạo lại "). –

Các vấn đề liên quan