Out of memory Exception in ListView and pagerview together - android

I create an application with ListView and ViewPager.
I used FragmentStatePagerAdapter as pageradapter.
when click on item in list, open an pagefragment to load detail data.
I monitor memory allocated in android studio monitor, when click on item
in list view memory is allocated.
My problem is here:
when back from pager to list,and click on item, memory is allocated again.
if I done this steps, an OutOfMemory is thrown.
I use
android:largeHeap="true"
But does not work for me.
Some piece of my code:
listview onItemClickListener:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//peace of code that create launch new fragment with swipe view inside
FragmentPager fragmentPager = new FragmentPager();
Bundle bundle = new Bundle();
bundle.putInt("CURRENT_POSITION", position);
bundle.putParcelableArrayList("DATA_LIST", data);
fragmentPager.setArguments(bundle);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.container, fragmentPager, "swipe_view_fragment");
ft.addToBackStack(null);
ft.commit();
}
});
My FragmentPager:
public class FragmentPager extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
if(v==null)
v = inflater.inflate(R.layout.fragment_pager, container, false);
if(mViewPager==null)
mViewPager = (ViewPager) v.findViewById(R.id.pager_view);
currentPosition = getArguments().getInt("CURRENT_POSITION");
data = getArguments().getParcelableArrayList("DATA_LIST");
FragmentItemPagerAdapter fragmentItemPagerAdapter = new FragmentItemPagerAdapter(getFragmentManager(), data,this.getActivity());
mViewPager.setOffscreenPageLimit(1);
mViewPager.setAdapter(fragmentItemPagerAdapter);
mViewPager.setCurrentItem(currentPosition);
fragmentItemPagerAdapter.notifyDataSetChanged();
return v;
}
}
and my FragmentItemPagerAdapter:
public class FragmentItemPagerAdapter extends FragmentStatePagerAdapter {
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
container.removeView(container);
/*if (position >= getCount()) {
container.removeAllViews();
FragmentManager manager = ((Fragment) object).getFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove((Fragment) object);
trans.commit();
}*/
}
}

Try this
put in Mainfest--->
<application
android:largeHeap="true"
>
.....
</application>
may it will help

May be your readFromParcel and writeToParcel methods doesn't match and if you can avoid to pass whole list of array to the fragment.

Related

replacing fragment with another fragment with OnClick on a Listview

public class Fragment_01 extends ListFragment {
String string[]={"Contact 1","Contact 2","Contact 3","Contact 4","Contact 5"};
public View onCreateView(LayoutInflater inflater, ViewGroup container ,Bundle saveInstanceState) {
View myview = inflater.inflate(R.layout.fragment_fragment_01, container, false);
ListView listView= (ListView) myview.findViewById(android.R.id.list);
ArrayAdapter<String> array = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1,string);
listView.setAdapter(array);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment_03 f3 = new Fragment_03();
ft.replace(R.id.linearLayout2, f3);
ft.commit();
}
});
return myview;
}
}
Do not change a fragment inside another. Have a frame layout n the activity. On click of an item in the list view, send the event to the activity through an interface and in the activity replace the fragment. This is the right way of replacing fragments.
Fragment_03 f3 = new Fragment_03();
FragmentManager fragmentManager = ((FragmentActivity) getContext()).getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, new Fragment_03())
.commit();
//I am using this code without listView and this is working fine then why the other is not working ??
public class Fragment_01 extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container ,Bundle saveInstanceState){
View myview=inflater.inflate(R.layout.activity_fragment_01,container,false);
Button btn = (Button) myview.findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fm =getFragmentManager();
FragmentTransaction ft =fm.beginTransaction();
Fragment_03 f3 = new Fragment_03();
ft.replace(R.id.linearLayout2,f3);
ft.commit();
}
});
return myview;
}
}

ViewPager is not showing in the middle of fragment

I added ViewPager for views(not fragments) located in the middle of the fragment, but for some reason it's not showing.
There is ViewGroup parent container for it (FrameLayout), viewpager added dynamically (also tried to insert it directly in layout).
May be I miss something.
Will be glad for any tip, thanks!
ViewPager:
public class TabsPagerAdapter extends PagerAdapter {
List<View> pages = null;
public TabsPagerAdapter(List<View> pages) {
this.pages = pages;
}
#Override
public int getCount() {
return pages.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
View v = pages.get(position);
collection.addView(v, 0);
return v;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
}
Fragment:
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_product, container, false);
FrameLayout pagerPlaceholder = (FrameLayout) root.findViewById(R.id.viewpager_placeholder);
List<View> pages = new ArrayList<>();
View page = LayoutInflater.from(getDashboardActivity()).inflate(R.layout.test_layout, null);
TextView textView = (TextView) page.findViewById(R.id.text_view);
textView.setText("Test1");
pages.add(page);
View page2 = LayoutInflater.from(getDashboardActivity()).inflate(R.layout.test_layout, null);
TextView textView2 = (TextView) page2.findViewById(R.id.text_view);
textView2.setText("Test2");
pages.add(page);
TabsPagerAdapter tabsPagerAdapter = new TabsPagerAdapter(pages);
ViewPager viewPager = new ViewPager(getDashboardActivity());
viewPager.setAdapter(tabsPagerAdapter);
pagerPlaceholder.addView(viewPager, 0,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return root;
}
fragment_product.xml
...
<LinearLayout
android:id="#+id/fragment_catalog_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="visible">
...
<FrameLayout
android:id="#+id/viewpager_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
I tried your code and found two clues, hope this will help:
Did you forget to commit the transaction of FragmentManager?
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.frament_container, new MyFragment());
transaction.commit();
The View page is added to the ArrayList pages twice, you need to add page2 at second page.add(page).
I just push the demo to github.
Please using getChildFragmentManager(); if you use NestedFragment.
Simple :
FragmentManager fragmentManager = getChildFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.frament_container, new MyFragment());
transaction.commit();

Fragment is recreate on back press from other Fragment

I am facing a problem in regarding fragment.
In my scenario,
There are two fragment associated with FragmentActivity.
In FragmentActivity, there are a container layout (Frame Layout) in which all fragment will replace.
public void replaceFragment(Fragment fragmentClass) {
String selectedFragment = fragmentClass.getClass().getName();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction
.replace(R.id.content_frame, fragmentClass);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
First time , I set a List type fragment (Fragment A) in which get the data from web service and papulate over listview. I execute the AsyncTask from onCreateView() method.
In MainActivity: onCreate
SherlockFragment fragment = new FragmentA();
replaceFragment(fragment);
On list item click of Fragment A, Fragment A will callback the activity method to replace it to details type fragment Fragment B.
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
callback = (ICallBack) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/*View rootView = inflater.inflate(R.layout.fragment_locate, container,
false);*/
View rootView = inflater.inflate(R.layout.fragment_a, container,
false);
ListView list = (ListView) rootView
.findViewById(R.id.listView);
adapter = new MyListAdapter();
list.setAdapter(adapter);
list
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,
View convertView, int position, long id) {
SherlockFragment fragment = new SalonDetailFragment();
callback.replaceFragment(fragment);
}
});
ListDataTask task = new ListDataTask();
task.execute();
return rootView;
}
class ListDataTask extends AsynTask<Void,Void,List<Data>>{
public Void doInBackground(Void parems){
List<Data> = getDataFromServer();
}
onPostExecute(List<Data> data){
adapter.addAllData(data);
adapter.notifyDataSetChanged();
}
}
When I press back button, from Fragment B then Application will show Fragment A but it execute Asynctask again and get the data to papulate the listview.
So I need to know, How to maintain the pervious state of Fragment like Activity.
Is there are any way to not to create Fragment after come back from Other activity
Have a look my pseudo code.
I got solution. Simple.... do the check null value of rootview
public class FragmentA extends Fragment {
View _rootView;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (_rootView == null) {
// Inflate the layout for this fragment
_rootView = inflater.inflate(R.layout.fragment_a, container, false);
// Find and setup subviews
_listView = (ListView)_rootView.findViewById(R.id.listView);
...
} else {
// Do not inflate the layout again.
// The returned View of onCreateView will be added into the fragment.
// However it is not allowed to be added twice even if the parent is same.
// So we must remove _rootView from the existing parent view group
// (it will be added back).
((ViewGroup)_rootView.getParent()).removeView(_rootView);
}
return _rootView
I have the same problem and solved by replacing
fragmentTransaction
.replace(R.id.content_frame, fragmentClass);
to
fragmentTransaction
.add(R.id.content_frame, fragmentClass);
Replace will always create new instance on back press while Add is just add a new fragment in Stack. for more information check this link

Calling a fragment from another fragment on click

What I want to do is to call one fragment from another on click on item of listview. Program builds without errors however it crash on click on item. Btw I’m making here local Fragment_3 object, I have got already done it in my mainactivity, how to pass it to this function?
Fragment_1.java content:
public class Fragment_1 extends SherlockFragment implements OnItemClickListener{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);
View view = inflater.inflate(R.layout.fragment_1, container, false);
ListView listView = (ListView) view.findViewById(R.id.listView1);
listView.setOnItemClickListener(this);
return view;
}
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// TODO Auto-generated method stub
Fragment Fragment3 = new Fragment_3();
Integer fragmentId = (Integer) v.getTag();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(fragmentId, Fragment3);
fragmentTransaction.commit();
}
}
My suspicion is that v.getTag() is null; So Integer fragmentId = (Integer) v.getTag(); will end up in fragmentId being null. When unboxing that to an int you'll get a NullPointerException. Why don't you replace fragmentId in fragmentTransaction.replace(fragmentId, Fragment3); with the id of the container that holds current instance of Fragment_1?

Replace Fragment onItemClick with ViewPager as its container

I want to replace a fragment containing a list of items with a new fragment depending on the item clicked. This is my code, how do I need to approach this? Should I declare my ListView, Adapter and such in onCreateView or onActivityCreated? The container is a ViewPager if that makes a difference.
public class PreferenceListFragment extends SherlockFragment
{
ListView lv;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return (LinearLayout)inflater.inflate(R.layout.settings, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
lv = (ListView)getView().findViewById(R.id.SettingsLV);
lv.setAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, Preferences.TITLES));
lv.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Log.i("FragmentList", "Item clicked: " + arg2);
// Switch case that starts fragment depending on 'position'.
Fragment1 f1 = new Fragment1();
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.pager, f1);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
}
);
}
}
Link to some very weird behaviour from my app.
The setting of adapter and listview should be done in onActivityCreated. OnCreateView is just to draw the user interface for the first time. The processing should be in onActivityCreated(). Refer http://developer.android.com/guide/topics/fundamentals/fragments.html

Categories

Resources