停止选项卡中的函数调用
Stop function calling in tabs
我的 android 中有 3 个滑动标签(A、B、C)。当涉及到选项卡 c 时,我有一个函数 RetrieveData()
,用于从 MySQL
检索数据并加载到 listView
.
假设在MySQL我只有一行数据,当涉及到c时,数据将被加载到listView(只有一个列表)。当我滑动到选项卡 A 并再次滑动到 C 时,列表现在变为 2。
有没有办法让 RetrieveData()
只调用一次?谢谢。
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View edit_details = inflater.inflate(R.layout.edit_work_details, container, false);
// EditDetails = new ArrayList<HashMap<String, String>>();
listViewUpdate = (ListView) edit_details.findViewById(R.id.listViewEdit);
totalHours=(TextView)edit_details.findViewById(R.id.hour);
setHasOptionsMenu(true);
Bundle bundle = this.getArguments();
if (getArguments() != null) {
ID = bundle.getString("ID");
RetrieveData(ID); // retrieve data from MySQL
}
Toast.makeText(getActivity(), "Details" + ID, Toast.LENGTH_LONG).show();
}
TabAdapter
public class TabsFragmentPagerAdapter extends FragmentPagerAdapter {
public TabsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int index) {
// TODO Auto-generated method stub
if(index == 0) {
Fragment fragment=new A();
Bundle bundle = new Bundle();
bundle.putString("ID", Edit.ID);
fragment.setArguments(bundle);
return fragment;
}
if(index == 1) {
Fragment fragment = new B();
Bundle bundle = new Bundle();
bundle.putString("ID", Edit.ID);
fragment.setArguments(bundle);
return fragment;
}
if(index == 2) {
Fragment fragment = new C();
Bundle bundle = new Bundle();
bundle.putString("ID", Edit.ID);
fragment.setArguments(bundle);
return fragment;
}
return null;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 3;
}
}
ViewPager代码
public class ActivityB extends ActionBarActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private ActionBar actionBar;
private TabsFragmentPagerAdapter tabsAdapter;
private String[] item = new String[]{"Information","Work Force","Work Details"};
private String id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
// id=getIntent().getExtras().getString("ID");
viewPager = (ViewPager) findViewById(R.id.viewPager);
tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(tabsAdapter);
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for(int i=0; i<4; i++){
actionBar.addTab(actionBar.newTab().setText(item[i]).setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int arg) {
// TODO Auto-generated method stub
actionBar.setSelectedNavigationItem(arg);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
@Override
public void onTabReselected(ActionBar.Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction arg1) {
// TODO Auto-generated method stub
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
}
这是我的标签 c
再次滑动到 A 和 C 后
好像又在调用 RetrieveData
。
您可以通过将 OffscreenPageLimit
设置为 2 到您的 ViewPager
实例来防止这种情况。
这是文档 -
/**
* Set the number of pages that should be retained to either side of the
* current page in the view hierarchy in an idle state. Pages beyond this
* limit will be recreated from the adapter when needed.
*
* <p>This is offered as an optimization. If you know in advance the number
* of pages you will need to support or have lazy-loading mechanisms in place
* on your pages, tweaking this setting can have benefits in perceived smoothness
* of paging animations and interaction. If you have a small number of pages (3-4)
* that you can keep active all at once, less time will be spent in layout for
* newly created view subtrees as the user pages back and forth.</p>
*
* <p>You should keep this limit low, especially if your pages have complex layouts.
* This setting defaults to 1.</p>
*
* @param limit How many pages will be kept offscreen in an idle state.
*/
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
您应该使用 setOffscreenPageLimit
个 ViewPager
。它将设置您首先要加载多少页寻呼机。
setOffScreeenPageLimit 的默认值为 1,因此它将加载当前页面和下一页。在您的情况下,它将加载 A
和 B
,当您从 B
移动到 C
时,它将破坏 A
.
的实例
尝试使用
`pager.setOffscreenPageLimit(2)`
它将加载当前页面和另外 2 个页面,因此 A、B 和 C 将加载一次。
编辑
Set the number of pages that should be retained to either side of the
current page in the view hierarchy in an idle state. Pages beyond this
limit will be recreated from the adapter when needed.
This is offered as an optimization. If you know in advance the number
of pages you will need to support or have lazy-loading mechanisms in
place on your pages, tweaking this setting can have benefits in
perceived smoothness of paging animations and interaction. If you have
a small number of pages (3-4) that you can keep active all at once,
less time will be spent in layout for newly created view subtrees as
the user pages back and forth.
这显然意味着你可以在初始级别设置要加载的页面数,如果你想首先加载5个页面运行,请将其值设置为4。
现在,如果您要从 5 个页面中的任何一个页面移动,Fragment
的 onCreateView()
将不会被调用,因为它已经在初始阶段加载。
如果每次滑动到 C
时都从数据库中检索,那么您需要事先清除列表,或者在输入片段时在 onResume
方法中,或者当您离开片段时,在 onPause
方法中。
这意味着要么清除你的 ArrayList
,并确保它不是 static
,要么意味着你必须使用 listView.setAdapter(null);
清除你的 ListView
.然后不要忘记在适配器上使用 notififyDatasetChanged()
。
由于您没有粘贴 RetrieveData() 代码,我假设您将数据读入 ArrayList<> 或遍历 cursor.And 也没有其他地方可以调用此方法,除了onCreateVie()。一些可能的解决方案可能是:
- 如果您明确设置 viewPager.setOffscreenPageLimit(x),其中 x>1,请删除该代码。默认情况下,此值为 1,View Pager 每次都会调用 createView。
- 当您使用 FragmentPagerAdapter 时,一旦您理想地加载了 C 片段,就不应再次创建它,因为它应该存在于内存中,如果您的 onCreateView() 是,ViewPager 将使用 that.Check每次为 C 片段调用。
- 请确保每次将您的数据检索到列表中时,您不是追加到列表中,而是清除列表然后添加它。
请尝试上面的方法。
许多答案建议使用 setOffscreenPageLimit,但我不推荐它有两个原因。
1)viewpager中的片段资源即使在屏幕外也不会被垃圾回收。如果您有像位图这样占用内存的对象,这将导致内存问题。
2) 当应用程序进入后台并再次进入前台时,这种方法是不够的。
我建议在ViewPager的每个fragment中将数据保存在onSaveInstanceState中,并检查onCreate中是否保存了数据。如果有数据,请显示它。否则,查询数据。
我以前遇到过类似的问题,问题出在我的代码上,在从数据库中获取日期时,我正在填充列表,每当页面刷新时它不会创建新列表,而是直接添加相同的列表中的数据已经包含数据并显示具有相同条目的两行。
为了解决这个问题,我在填充数据之前清除了我的列表。
我的 android 中有 3 个滑动标签(A、B、C)。当涉及到选项卡 c 时,我有一个函数 RetrieveData()
,用于从 MySQL
检索数据并加载到 listView
.
假设在MySQL我只有一行数据,当涉及到c时,数据将被加载到listView(只有一个列表)。当我滑动到选项卡 A 并再次滑动到 C 时,列表现在变为 2。
有没有办法让 RetrieveData()
只调用一次?谢谢。
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View edit_details = inflater.inflate(R.layout.edit_work_details, container, false);
// EditDetails = new ArrayList<HashMap<String, String>>();
listViewUpdate = (ListView) edit_details.findViewById(R.id.listViewEdit);
totalHours=(TextView)edit_details.findViewById(R.id.hour);
setHasOptionsMenu(true);
Bundle bundle = this.getArguments();
if (getArguments() != null) {
ID = bundle.getString("ID");
RetrieveData(ID); // retrieve data from MySQL
}
Toast.makeText(getActivity(), "Details" + ID, Toast.LENGTH_LONG).show();
}
TabAdapter
public class TabsFragmentPagerAdapter extends FragmentPagerAdapter {
public TabsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int index) {
// TODO Auto-generated method stub
if(index == 0) {
Fragment fragment=new A();
Bundle bundle = new Bundle();
bundle.putString("ID", Edit.ID);
fragment.setArguments(bundle);
return fragment;
}
if(index == 1) {
Fragment fragment = new B();
Bundle bundle = new Bundle();
bundle.putString("ID", Edit.ID);
fragment.setArguments(bundle);
return fragment;
}
if(index == 2) {
Fragment fragment = new C();
Bundle bundle = new Bundle();
bundle.putString("ID", Edit.ID);
fragment.setArguments(bundle);
return fragment;
}
return null;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 3;
}
}
ViewPager代码
public class ActivityB extends ActionBarActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private ActionBar actionBar;
private TabsFragmentPagerAdapter tabsAdapter;
private String[] item = new String[]{"Information","Work Force","Work Details"};
private String id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
// id=getIntent().getExtras().getString("ID");
viewPager = (ViewPager) findViewById(R.id.viewPager);
tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(tabsAdapter);
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for(int i=0; i<4; i++){
actionBar.addTab(actionBar.newTab().setText(item[i]).setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int arg) {
// TODO Auto-generated method stub
actionBar.setSelectedNavigationItem(arg);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
@Override
public void onTabReselected(ActionBar.Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction arg1) {
// TODO Auto-generated method stub
viewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
}
这是我的标签 c
再次滑动到 A 和 C 后
好像又在调用 RetrieveData
。
您可以通过将 OffscreenPageLimit
设置为 2 到您的 ViewPager
实例来防止这种情况。
这是文档 -
/**
* Set the number of pages that should be retained to either side of the
* current page in the view hierarchy in an idle state. Pages beyond this
* limit will be recreated from the adapter when needed.
*
* <p>This is offered as an optimization. If you know in advance the number
* of pages you will need to support or have lazy-loading mechanisms in place
* on your pages, tweaking this setting can have benefits in perceived smoothness
* of paging animations and interaction. If you have a small number of pages (3-4)
* that you can keep active all at once, less time will be spent in layout for
* newly created view subtrees as the user pages back and forth.</p>
*
* <p>You should keep this limit low, especially if your pages have complex layouts.
* This setting defaults to 1.</p>
*
* @param limit How many pages will be kept offscreen in an idle state.
*/
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
您应该使用 setOffscreenPageLimit
个 ViewPager
。它将设置您首先要加载多少页寻呼机。
setOffScreeenPageLimit 的默认值为 1,因此它将加载当前页面和下一页。在您的情况下,它将加载 A
和 B
,当您从 B
移动到 C
时,它将破坏 A
.
尝试使用
`pager.setOffscreenPageLimit(2)`
它将加载当前页面和另外 2 个页面,因此 A、B 和 C 将加载一次。
编辑
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.
This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.
这显然意味着你可以在初始级别设置要加载的页面数,如果你想首先加载5个页面运行,请将其值设置为4。
现在,如果您要从 5 个页面中的任何一个页面移动,Fragment
的 onCreateView()
将不会被调用,因为它已经在初始阶段加载。
如果每次滑动到 C
时都从数据库中检索,那么您需要事先清除列表,或者在输入片段时在 onResume
方法中,或者当您离开片段时,在 onPause
方法中。
这意味着要么清除你的 ArrayList
,并确保它不是 static
,要么意味着你必须使用 listView.setAdapter(null);
清除你的 ListView
.然后不要忘记在适配器上使用 notififyDatasetChanged()
。
由于您没有粘贴 RetrieveData() 代码,我假设您将数据读入 ArrayList<> 或遍历 cursor.And 也没有其他地方可以调用此方法,除了onCreateVie()。一些可能的解决方案可能是:
- 如果您明确设置 viewPager.setOffscreenPageLimit(x),其中 x>1,请删除该代码。默认情况下,此值为 1,View Pager 每次都会调用 createView。
- 当您使用 FragmentPagerAdapter 时,一旦您理想地加载了 C 片段,就不应再次创建它,因为它应该存在于内存中,如果您的 onCreateView() 是,ViewPager 将使用 that.Check每次为 C 片段调用。
- 请确保每次将您的数据检索到列表中时,您不是追加到列表中,而是清除列表然后添加它。
请尝试上面的方法。
许多答案建议使用 setOffscreenPageLimit,但我不推荐它有两个原因。
1)viewpager中的片段资源即使在屏幕外也不会被垃圾回收。如果您有像位图这样占用内存的对象,这将导致内存问题。
2) 当应用程序进入后台并再次进入前台时,这种方法是不够的。
我建议在ViewPager的每个fragment中将数据保存在onSaveInstanceState中,并检查onCreate中是否保存了数据。如果有数据,请显示它。否则,查询数据。
我以前遇到过类似的问题,问题出在我的代码上,在从数据库中获取日期时,我正在填充列表,每当页面刷新时它不会创建新列表,而是直接添加相同的列表中的数据已经包含数据并显示具有相同条目的两行。 为了解决这个问题,我在填充数据之前清除了我的列表。