我有一个有一个主要活动的应用。此活动包含对fragmentManager的引用,以及我在应用程序中使用的所有片段。加载主活动后,它会显示一个"导航片段",此片段包含一个ViewPager,它本身使用片段显示菜单项(使用FragmentPagerAdapter完成)。当我选择菜单项(通过单击它或使用手势)时,当前导航片段将被菜单项片段替换为:
public void replaceFragment(Fragment frag, String fragTag) {
Fragment currentFrag = mFragmentManager.findFragmentById(R.id.fragmentContainer);
mFragmentManager.beginTransaction()
.remove(currentFrag)
.add(R.id.fragmentContainer, frag, fragTag)
.addToBackStack(null)
.commit();
}
当我从菜单项片段返回到导航片段时,使用:
fragmentManager.popBackStackImmediate();
我在分配的内存中获得大幅跳跃。选择菜单项并返回导航片段大约8-10次后,我的记忆开始填满,我的sensorListeners停止工作,所以我不能使用手势。我尝试尽可能多地重用片段,并保持每个片段的onCreateView()方法不受任何实例化的影响。
当我选择菜单项片段然后多次返回导航片段时,这就是我的内存监视器输出的内容:
有谁知道可能导致这种情况的原因?
这是我的导航片段' MainFragment':
public class MainFragment extends Fragment {
private MainWearActivity mMainWearActivity;
View view;
private int currentPage;
private ViewPager pager;
private ViewPagerAdapter adapter;
private WearYFlick mYFlick;
private WearXFlick mXFlick;
private Vibrator vibrator;
private OnShakeListener yFlickListener;
private OnShakeListener xFlickListener;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainWearActivity = (MainWearActivity) getActivity();
vibrator = mMainWearActivity.getVibrator();
adapter = new ViewPagerAdapter((MainWearActivity)getActivity(),getChildFragmentManager());
mYFlick = new WearYFlick();
mXFlick = new WearXFlick();
yFlickListener = new OnShakeListener() {
@Override
public void onShake() {
yFlickDetected();
}
};
xFlickListener = new OnShakeListener() {
@Override
public void onShake() {
xFlickDetected();
}
};
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
// Scrolling menu
pager = (ViewPager) view.findViewById(R.id.watchNavPager);
pager.setAdapter(adapter);
pager.addOnPageChangeListener(adapter);
// Set current item to the middle page
pager.setCurrentItem(Consts.FIRST_PAGE);
currentPage = Consts.FIRST_PAGE;
// Set number of pages
pager.setOffscreenPageLimit(4);
// Set no margin so other pages are hidden
pager.setPageMargin(0);
// Set the listeners and start listening
mYFlick.setOnShakeListener(yFlickListener);
mXFlick.setOnShakeListener(xFlickListener);
return view;
}
@Override
public void onPause() {
Log.d("FRAG", "MainFragment onPause() called");
stopListening();
super.onPause();
}
@Override
public void onResume() {
super.onResume();
Log.d("FRAG", "MainFragment onResume() called");
startListening();
}
private void startListening(){
mMainWearActivity.registerListener(mYFlick, Consts.GYRO);
mMainWearActivity.registerListener(mXFlick, Consts.GYRO);
}
private void stopListening(){
mMainWearActivity.unregisterListener(mYFlick);
mMainWearActivity.unregisterListener(mXFlick);
}
private void yFlickDetected(){
vibrator.vibrate(Consts.vibPattern, -1);
currentPage = pager.getCurrentItem();
currentPage++;
pager.setCurrentItem(currentPage, true);
}
private void xFlickDetected(){
vibrator.vibrate(Consts.vibPattern, -1);
// Select the current menu item
switch (mMainWearActivity.getCurrentSelection()) {
case Consts.MENU_ITEM:
mMainWearActivity.replaceFragment(mMainWearActivity.getFragment(Consts.FRAG_ITEM), Consts.FRAG_ITEM);
break;
}
}
@Override
public void onDestroyView() {
pager = null;
super.onDestroyView();
}
}
这是我的菜单项片段:
public class VoiceFragment extends Fragment {
private View view;
private MainWearActivity mMainWearActivity;
private Vibrator vibrator;
private FragmentManager fManager;
private WearYShake mYShake;
private WearYFlick mYFlick;
private TextView menuItemText;
private ImageView mainImageView;
private ColorStateList defaultTextColor;
private OnShakeListener yFlickListener;
private OnShakeListener yShakeListener;
private View.OnClickListener imgClickListener;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainWearActivity = (MainWearActivity) getActivity();
vibrator = mMainWearActivity.getVibrator();
fManager = mMainWearActivity.getFragManager();
mYShake = new WearYShake();
mYFlick = new WearYFlick();
yFlickListener = new OnShakeListener() {
@Override
public void onShake() {
yFlickDetected();
}
};
yShakeListener = new OnShakeListener() {
@Override
public void onShake() {
yShakeDetected();
}
};
imgClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
yFlickDetected();
}
};
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_menu_item, container, false);
menuItemText = (TextView) view.findViewById(R.id.menuItemFragTxt);
mainImageView= (ImageView) view.findViewById(R.id.itemMainImg);
mYFlick.setOnShakeListener(yFlickListener);
mYShake.setOnShakeListener(yShakeListener);
mainImageView.setOnClickListener(imgClickListener);
return view;
}
private void promptSpeechInput(){
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, Consts.PROMPT_SPEECH);
try {
startActivityForResult(intent, Consts.REQ_CODE_SPEECH_INPUT);
} catch (ActivityNotFoundException a) {
Toast.makeText(getActivity(), Consts.VOICE_ERROR_MSG, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Consts.REQ_CODE_SPEECH_INPUT: {
if (resultCode == Activity.RESULT_OK && null != data) {
ArrayList<String> result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
menuItemText.setText(result.get(0));
}
break;
}
}
}
@Override
public void onPause() {
Log.d("FRAG", "ItemFragment onPause() called");
stopListening();
super.onPause();
}
@Override
public void onResume() {
super.onResume();
Log.d("FRAG", "ItemFragment onResume() called");
startListening();
}
private void startListening(){
mMainWearActivity.registerListener(mYFlick, Consts.GYRO);
mMainWearActivity.registerListener(mYShake, Consts.ACCEL);
}
private void stopListening(){
mMainWearActivity.unregisterListener(mYFlick);
mMainWearActivity.unregisterListener(mYShake);
}
private void yFlickDetected(){
vibrator.vibrate(Consts.vibPattern, -1);
fManager.popBackStackImmediate();
}
private void yShakeDetected(){
vibrator.vibrate(Consts.vibPattern, -1);
promptSpeechInput();
}
}
我的ViewPagerAdapter看起来像这样:
public class ViewPagerAdapter extends FragmentPagerAdapter implements
ViewPager.OnPageChangeListener {
private MainWearActivity context;
private FragmentManager fm;
public ViewPagerAdapter(MainWearActivity context, FragmentManager fm) {
super(fm);
this.fm = fm;
this.context = context;
}
@Override
public Fragment getItem(int position)
{
position = position % Consts.PAGES;
switch(position){
case Consts.ITEM1_POS:
return new AdapterItem1Fragment();
case Consts.ITEM2_POS:
return new AdapterItem2Fragment();
case Consts.ITEM3_POS:
return new AdapterItem3Fragment();
case Consts.ITEM4_POS:
return new AdapterItem4Fragment();
default:
return null;
}
}
@Override
public int getCount()
{
return Consts.PAGES * Consts.LOOPS;
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {}
@Override
public void onPageSelected(int position) {}
@Override
public void onPageScrollStateChanged(int state) {}
}
任何人都可以看到为什么在我的主导航片段和菜单项片段之间切换可能会导致内存分配如此大的跳跃并阻止我的传感器工作?感谢。