I have a Fragment with a TableLayout. The data in the table is from a SQLite db. The SQLite db is populated from a RESTful webservice in an AsyncTask in the MainActivity. The Fragment must wait for the task to complete before populating the table. The Fragment listens for the task onPostExecute() method to be called. When it is, the method onLoadAndStoreComplete in the Fragment is called. This all works.
What doesn't work is that I need the fragment activity in order to create new TableRows and TextViews in onLoadAndStoreComplete and I can't get it.
I've tried:
- making a class member fragmentActivity and assigning in onCreateView(), but by the time it gets to onLoadAndStoreComplete(), it is null.
- calling this.getActivity() again in onLoadAndStoreComplete(), but it returns null.
How do I get the fragment activity?
MyFragment.java:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
fragmentActivity = this.getActivity(); // return value is valid
...
}
#Override
public void onLoadAndStoreComplete() {
fragmentActivity = this.getActivity(); // returns null
...
}
from MainActivity.java (extends ActionBarActivity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = this;
setContentView(R.layout.activity_main);
Resources resources = getResources();
String[] tabTitleArray = { resources.getString(R.string.first_fragment),
resources.getString(R.string.second_fragment),
resources.getString(R.string.help_fragment) };
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
mAdapter = new TabsPagerAdapter(this.getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tab_name : tabTitleArray) {
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
// On swiping the ViewPager, select the respective tab
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position) ;// on changing the page, make respected tab selected
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
String url = "http://myrestfulwebservice";
Fragment secondFragment = mAdapter.getItem(SECOND_TAB);
new LoadAndStoreDataTask((OnLoadAndStoreCompleteListener)secondFragment).execute(url);
}
} // end OnCreate
TabsPagerAdapter.java
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
case 2:
return new HelpFragment();
}
return null;
}
#Override
public int getCount() {
return 3; // get item count - equal to number of tabs
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++) {
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#FF0000")); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#0000FF")); // selected
}
}
I haven't tested this, but it seems to me that it would work.
Add a Context parameter to the constructor for both TabsPagerAdapter and MyFragment.
Something like this:
TabsPagerAdapter.java:
public class TabsPagerAdapter extends FragmentPagerAdapter {
private Context mCtx;
public TabsPagerAdapter(FragmentManager fragmentManager, Context context) {
super(fragmentManager);
mCtx = context;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstFragment(mCtx);
case 1:
return new SecondFragment(mCtx);
case 2:
return new HelpFragment(mCtx);
}
return null;
}
#Override
public int getCount() {
return 3; // get item count - equal to number of tabs
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++) {
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#FF0000")); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#0000FF")); // selected
}
}
MainActivity.java:
mAdapter = new TabsPagerAdapter(this.getSupportFragmentManager(), this);
MyFragment.java (do this in FirstFragment, SecondFragment, and HelpFragment):
public static class MyFragment extends Fragment {
private Context fragmentActivity ;
public MyFragment(Context context){
fragmentActivity = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//.........
return rootView;
}
#Override
public void onLoadAndStoreComplete() {
//do something with fragmentActivity
}
}
It seems the AsyncTask starts too early. suggest loading the db in onActivityCreated(), it's be called after onCreateView
#Override
public void onActivityCreated (Bundle savedInstanceState) {
//load your db here
}
Related
Activity
public class GroupesActivity extends BaseActivity {
SelectedBundle selectedBundle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_groupes);
sectionsPagerAdapter = new GroupPagerAdapter(this, getSupportFragmentManager());
viewPager.setAdapter(sectionsPagerAdapter);
tabs.setupWithViewPager(viewPager);
}
private void getAllGroup() {
// api call retrive data
// send data using interface on response
// set data selectedBundle.onBundleSelect(isVisible,calanderModelList,groupModelList,eventModelList);
}
public void setOnBundleSelected(SelectedBundle selectedBundle) {
this.selectedBundle = selectedBundle;
}
public interface SelectedBundle {
void onBundleSelect(boolean isVisible, List<CalanderModel> calanderModelList, List<GroupModel> groupModelList, List<EventModel> eventModelList);
}
}
Frgment
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_all_groups_fragments, container, false);
// get data only once on oncreateview
((GroupesActivity) getActivity()).setOnBundleSelected(new GroupesActivity.SelectedBundle() {
#Override
public void onBundleSelect(boolean isVisible, List<CalanderModel> calanderModelListtt, List<GroupModel> groupModelList, List<EventModel> eventModelList) {
Log.e("retrive data","data")
}
});
return root;
}
}
GroupPagerAdapter
public class GroupPagerAdapter extends FragmentPagerAdapter {
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
public GroupPagerAdapter(Context context, FragmentManager fm) {
super( fm);
this.mContext=context;
}
#NonNull
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new AllGroupsFragments();
case 1:
return new HostFragments();
case 2:
return new GuestFragments();
}
return null;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
#Override
public int getCount() {
return 3;
}
}
problem
i have three fragments in tabview when i swipe this obove fragment
and then come again in this fragmnet that interface not called and i'm
not getting data from activity
How to get that data again from its parent activity, i need to only
retrive that data from activity on each time of fragments oncreateView
Thanks in adavance ;)
Use setMenuVisibility() method in Fragment to fix the issue.
//In fragments
#Override
public void setMenuVisibility(final boolean isVisible) {
super.setMenuVisibility(isVisible);
if (isVisible) {
//visible to user- do ur stuff
((GroupesActivity) getActivity()).setOnBundleSelected(new
GroupesActivity.SelectedBundle() {
#Override
public void onBundleSelect(boolean isVisible, List<CalanderModel>
calanderModelListtt, List<GroupModel> groupModelList, List<EventModel>
eventModelList) {
Log.e("retrive data","data")
}
});
}
}
the following link may help if you face any issues:
How to determine when Fragment becomes visible in ViewPager
I am new to Android.Its my first application.I have tried searching on Internet but everyone tried to pass simple data from activity to fragment.I want to pass an whole object from activity to fragment.
I know there is one solution around is just use serialize & de-serialize & put the data in Bundle.
Instead trying serialize & deserialize,I created a non-static method in my activity & trying to getActivity() in fragment & then calling that method but it returns me null.Can anybody help me with what I am doing wrong.
Below is my code:-
BaseDefaultActivity is my own customized class which extends AppCompatActivity.
public class EventDetailActivity extends BaseDefaultActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setBaseContentView(R.layout.activity_event_detail);
ButterKnife.bind(this);
initialiseDataFromIntend();
DummyObject obj=new DummyObj();
setDataObject(obj);
// Get the ViewPager and set it's PagerAdapter so that it can display items
viewPager.setAdapter(new EventDetailFragementAdapter(getSupportFragmentManager(), EventDetailActivity.this));
// Give the TabLayout the ViewPager
tabLayout.setupWithViewPager(viewPager);
}
}
public class BaseDefaultActivity extends AppCompatActivity implements BaseActivity {
private Object dataObj;
public void setDataObject(Object obj) {
this.dataObj = obj;
}
public Object getDataObj() {
return this.dataObj;
}
}
public class EventDetailFragementAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[]{"Tab1", "Tab2", "Tab3"};
private Context context;
public EventDetailFragementAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new EventDetailFragement();
break;
case 1:
fragment = new EventBasicInfoFragement();
break;
default:
fragment = new EventDetailFragement();
break;
}
return fragment;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
public class EventDetailFragement extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.event_detail_fragement, container, false);
TextView textView = (TextView) view;
textView.setText("AAAAAAA #" + (SearchEventResponseObject) ((BaseDefaultActivity) getActivity()).getDataObj());
return view;
}
}
I'm having an Activity that hosts two Fragments. One which contains an EditText and one that shows the input in a GridView. Fragment1 implements an interface to notify when the user wants to save the input. In the Activity I want to pass the data to the ArrayAdapter of Fragment2 but here I get the NullPointerException.
Activity:
public class SwipeTest extends FragmentActivity implements TestFragment1
.OnFragmentInteractionListener {
private final String[] tabs = {"Test 1", "Test 2"};
private ViewPager pager;
private ActionBar actionBar;
private TabsPagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.pager = new ViewPager(this);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup
.LayoutParams.MATCH_PARENT,
ViewGroup
.LayoutParams.MATCH_PARENT);
this.pager.setLayoutParams(params);
setContentView(this.pager);
this.actionBar = getActionBar();
this.adapter = new TabsPagerAdapter(
getSupportFragmentManager());
this.pager.setAdapter(this.adapter);
this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
setUpViewPager();
setUpActionBar();
}
/**
* Sets up the ViewPager and adds an OnPageChangeListener
*/
private void setUpViewPager() {
this.pager.setAdapter(this.adapter);
// pager needs an id; crashes if it has none
this.pager.setId(123456789);
// Set up the listener
ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager
.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i2) {
}
#Override
public void onPageSelected(int i) {
SwipeTest.this.actionBar.setSelectedNavigationItem(i);
}
#Override
public void onPageScrollStateChanged(int i) {
}
};
this.pager.setOnPageChangeListener(onPageChangeListener);
}
/**
* Sets up the ActionBar with it's tabs and adds an ActionBar.TabListener to
* them
*/
private void setUpActionBar() {
this.actionBar = getActionBar();
this.actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set up listener
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction
fragmentTransaction) {
SwipeTest.this.pager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction
fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction
fragmentTransaction) {
}
};
for (String tab_name : this.tabs) {
this.actionBar.addTab(
this.actionBar.newTab()
.setText(tab_name)
.setTabListener(tabListener));
}
}
/**
* Interface method of Fragment1
*/
#Override
public void onFragmentInteraction(String s) {
// This gets the fragment correct
TestFragment2 fragment = (TestFragment2) ((TabsPagerAdapter) pager
.getAdapter()).getItem(1);
// This assigns null to adapter
ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment
.getAdapter();
adapter.add(s);
adapter.notifyDataSetChanged();
}
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new TestFragment1();
case 1:
return new TestFragment2();
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
}
Fragment1:
public class TestFragment1 extends Fragment {
private OnFragmentInteractionListener mListener;
private EditText edit;
public TestFragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
LinearLayout layout = new LinearLayout(getActivity());
layout.setLayoutParams(params);
this.edit = new EditText(getActivity());
Button btn = new Button(getActivity());
btn.setText("Save");
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onButtonPressed();
}
});
layout.addView(this.edit);
layout.addView(btn);
return layout;
}
public void onButtonPressed() {
if (this.mListener != null) {
String input = this.edit.getText().toString();
this.mListener.onFragmentInteraction(input);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
this.mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement " +
"OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
this.mListener = null;
}
public interface OnFragmentInteractionListener {
public void onFragmentInteraction(String s);
}
}
Fragment2:
public class TestFragment2 extends Fragment {
private final List<String> data = new ArrayList<String>();
private ArrayAdapter<String> adapter;
public TestFragment2() {
// Required empty public constructor
}
public ArrayAdapter getAdapter() {
return this.adapter;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
GridView view = new GridView(getActivity());
GridView.LayoutParams params = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(params);
this.data.add("Hello");
this.data.add("World");
this.adapter = new ArrayAdapter(getActivity(),
android.R.layout
.simple_list_item_1,
this.data);
view.setAdapter(this.adapter);
return view;
}
}
I don't know why ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment.getAdapter(); is null. So, how do I get access to the fields of Fragment2?
It seems problem about lifecycle. As you may know, onCreateView() is async method, so fragment instance could be accessed before setAdapter().
My suggestion is to create TestFragment2 instance in SwipeTest#onCreate(). Also, your code creates new instance every time button pressed. It seems not good idea.
The problem was within the PagerAdapter. I used getItem() to recieve the Fragment which is bound to the tab's position. The mistake was that I returned a new instance of that Fragment instead of returning the existing Fragment. Since that new Fragment has never been shown the Fragment's onCreateView() and hence setUpAdapter() has never been called. That's why I recieved NPE in
ArrayAdapter<String> adapter = (ArrayAdapter<String>) fragment
.getAdapter();
adapter.add(s);
Approach[*]:
public class TabsPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<Fragment>();
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
mFragments.add(0, new TestFragment1());
mFragments.add(1, new TestFragment2());
}
#Override
public Fragment getItem(int index) {
if (index > (mFragments.size() - 1) )
return null;
return mFragments.get(index);
}
#Override
public int getCount() {
return mFragments.size();
}
}
[*] Untested since I changed my code and don't use the PagerAdapter anymore but I think the solution is comprehensible.
If the pager has never shown the second fragment, when your fragment1 interface callback is called the pager returns null:
// This gets the fragment correct
TestFragment2 fragment = (TestFragment2) ((TabsPagerAdapter) pager
.getAdapter()).getItem(1);
So your subsequent call to getAdapter() will result in the NPE.
I'm trying to pass a string between two fragments in a viewpager but I didn't found the right way to do it.
Here is my code so far :
public class MyFragmentPagerAdapter extends FragmentPagerAdapter{
final int PAGE_COUNT = 6;
/** Constructor of the class */
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
/** This method will be invoked when a page is requested to create */
#Override
public Fragment getItem(int arg0) {
switch (arg0) {
case 0:
return new MyFragment();
case 1:
return new part2();
case 2:
return new Part3();
case 3:
return new Part4();
case 4:
return new Part5();
case 5:
return new Part6();
default:
return null;
}
}
/** Returns the number of pages */
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
return "Page #" + ( position + 1 );
}
}
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/** Getting a reference to the ViewPager defined the layout file */
ViewPager pager = (ViewPager) findViewById(R.id.pager);
/** Getting fragment manager */
FragmentManager fm = getSupportFragmentManager();
/** Instantiating FragmentPagerAdapter */
MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);
/** Setting the pagerAdapter to the pager object */
pager.setAdapter(pagerAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
I'm not using tabs with the viewpager. What should I write in the fragments?
UPDATE :
I tried to implement an interface like suggested in the answers :
public interface OnTogglePressListener {
public void onTogglePressed(String msg);
}
On the first fragment :
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
try {
buttonListener = (OnTogglePressListener) getActivity();
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement onTogglePressed");
}
super.onAttach(activity);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
buttonListener.onTogglePressed("Off");
... }
On the second fragment :
public String getEtat(String etat)
{ state =etat;
return etat;
}
On the main activity :
public void onTogglePressed(String etat)
{
Part5 p = (Part5)getSupportFragmentManager().findFragmentById(R.layout.frag_2);
p.getEtat(etat);
}
But I got a NullPointerException everytime.
You're obviously using ViewPager and you can take advantage of it. You can add a tag to a ViewPager like this:
Activity:
pager.setTag("some text"); // pager is a ViewPager object
Then you can get this data via ViewGroup in a fragment like this:
Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
String result = container.getTag().toString();
// do something with the result
return view;
You can also setTag() to the container in the fragment.
This is the cleanest solution I found for sending data among fragments and their mother activity. Another solution (not mentioned here so far) is sending data through SharedPreferences, but I would suggest using tags if possible.
So i found the solution, the implementation is correct, the only thing that I should do the treatement I want in the method on the second fragment and that's it !
I have a viewpager with 2 pages, on each fragment i put a button to switching fragment,
but if i change orientation switching doesn't work.
For switching fragment I using my OnChangePageButtonClick interface
Why is this happening?
ViewPager Activity:
public class ViewPagerMusic extends FragmentActivity implements OnChangePageButtonClick {
private ViewPager vp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager_music);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
vp = (ViewPager)findViewById(R.id.viewpager);
vp.setAdapter(viewPagerAdapter);
}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
MainPage mainPage = new MainPage();
mainPage.setOnChengeButtonListener(ViewPagerMusic.this);
return mainPage;
case 1:
PlaylistPage playlistPage = new PlaylistPage();
playlistPage.setOnChengeButtonListener(ViewPagerMusic.this);
return playlistPage;
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
#Override
public void selectPage(int page) {
vp.setCurrentItem(page);
}
}
my Frgamnets:
public class MainPage extends Fragment {
public MainPage() {
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.music_main_page, container, false);
ImageButton btnPlaylist = (ImageButton)v.findViewById(R.id.btnGoPlaylist2);
btnPlaylist.setOnClickListener(onButtonListener);
return v;
}
private OnClickListener onButtonListener = new OnClickListener() {
#Override
public void onClick(View view) {
onChangePageButtonClick.selectPage(1);
}
};
public void setOnBackButtonListener(OnChangePageButtonClick onChangePageButtonClick) {
this.onChangePageButtonClick = onChangePageButtonClick;
}
private OnChangePageButtonClick onChangePageButtonClick;
}
Playlist fragment is similar to MainPage fragment.
Your fragments are storing a reference to the ViewPagerMusic activity. However, after rotation, the activity is destroyed and recreated, so the fragments now contain a reference to the old activity.
Instead of storing a reference to the activity, you can call the activity's method from the fragment like this:
((ViewPagerMusic) getActivity()).selectPage(1);
just create this method in your view pager
#Override
public void selectPage(int page) {
vp.setCurrentItem(page);
}
and then call this in your onclick method
((ViewPagerMusic) getActivity()).selectPage(1);