fragment is already active while calling Fragment.setArguments() - android

I am creating an activity which shows a list of videos(VideoListingActivity) depending on the parameters passed from the parent activity.my I am trying to pass the bundle passed to VideoListingActivity to its child fragment so that it can fetch the related data from database and display it on the activity. I am trying to use Fragment.setArguments() to pass the bundle to fragment but getting the below error .
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rrdtech.vidyavaan.android/com.rrdtech.vidyavaan.android.VideoListingActivity}: java.lang.IllegalStateException: Fragment already active
I think the fragment is attached to activity post to onCreate() so should this error even be raised ?
Below are the codes for my activity and fragment
VideoListingActivity.java
public class VideoListingActivity extends ActionBarActivity implements FilterFragment.OnFilterItemSelectedListener,
android.support.v7.widget.SearchView.OnQueryTextListener
{
public VideoListFragment videoListFragment;
private android.support.v7.widget.SearchView searchView;
private Context context;
private Bundle bundle;
private String listBy;
private String subjectId;
private String levelType;
private FragmentTransaction ft;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_listing);
// videoListFragment=new VideoListFragment();
videoListFragment= (VideoListFragment) getFragmentManager().findFragmentById(R.id.frg_video_listing_video_listing_fragment);
ft =getFragmentManager().beginTransaction();
context=this;
bundle = new Bundle();
bundle = getIntent().getExtras();
videoListFragment.setArguments(bundle);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_video_listing, menu);
MenuItem menuItem=menu.findItem(R.id.item_action_search);
//SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (android.support.v7.widget.SearchView) menu.findItem(R.id.item_action_search).getActionView();
setupSearchView(menuItem);
//searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
return super.onCreateOptionsMenu(menu);
}
public void setupSearchView(MenuItem searchItem)
{
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if(searchManager != null)
{
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(info);
}
searchView.setOnQueryTextListener(this);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onFilterItemSelected(String filterId) {
videoListFragment.filterSelectedAction("filter id is "+filterId);
}
#Override
public boolean onQueryTextSubmit(String query) {
CommonFunctions commonFunctions = new CommonFunctions();
commonFunctions.showProgressDialog(context,"getting data","bringing");
ft.replace(R.id.frg_video_listing_filter_fragment,videoListFragment);
ft.commit();
commonFunctions.dismissProgressDialog();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
}
VideoListingFragment.java
public class VideoListFragment extends Fragment {
private ListView videoListView;
private Context activityContext;
private VideosListAdapter listAdapter;
private List<Video> videosList;
private Bundle b;
private String listBy;
private String subjectId;
private String levelType;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
activityContext = activity.getApplicationContext();
b=new Bundle();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.video_list_fragment,container,false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
b= getArguments();
listBy = b.getString(VidyavaanGlobal.listBy);
Log.d("list by ",listBy);
}
#Override
public void onStart() {
super.onStart();
}
public void filterSelectedAction(String x)
{
Log.d("passed is ", x);
}
public void fillData()
{
videosList.add(new Video("chapter1","title1", "pragyan public school", "pawan saraskar", "Chemistry", "Advance", "abcd url", "21", "5/6/2015", "thumbnail url"));
videosList.add(new Video("chapter2","title2","pragyan public school","pawan saraskar","physics","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter3","title3","pragyan public school","pawan saraskar","english","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter4","title4","pragyan public school","pawan saraskar","Chemistry","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter5","title5","pragyan public school","pawan saraskar","Chemistry","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter6","title6","pragyan public school","pawan saraskar","Chemistry","Advance","abcd url","21","5/6/2015","thumbnail url"));
videosList.add(new Video("chapter7", "title7", "pragyan public school", "pawan saraskar", "Chemistry", "Advance", "abcd url", "21", "5/6/2015", "thumbnail url"));
}
public void displayVideoList(boolean searchReqeust )
{
}
public void displayVideoList(String pListBy, String pValue)
{
listAdapter = new VideosListAdapter(activityContext,videosList);
videoListView.setAdapter(listAdapter);
}
public void displayVideoList(String subjectId, String videoType, String VideoLevel)
{
}
}
can one please help. Thanks in advance.

From the Official Android development Reference:
Public void setArguments (Bundle args) Supply the construction
arguments for this fragment. This can only be called before the
fragment has been attached to its activity; that is, you should call
it immediately after constructing the fragment. The arguments supplied
here will be retained across fragment destroy and creation.
Your fragment is already attached to its activity i suggest you to use your own method, you don't need setArguments!
create your own setUIArguments(Bundle args) inside the fragment class and update the fragment UI inside this method
You will call this method in this way:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Detailfragment detailFragment = (Detailfragment)getFragmentManager().findFragmentById(detailFragmentID);
Bundle bundle = new Bundle();
bundle.putSerializable(BUNDLE_KEY, obj);// passing this object
detailFragment.setUIArguments(bundle); /* your new method */
}
in your fragment class
public void setUIArguments(Bundle args) {
getActivity().runOnUiThread(new Runnable() {
public void run() {
/* do your UI stuffs */
}
}
}

call
bundle = new Bundle();
bundle = getIntent().getExtras();
videoListFragment.setArguments(bundle);
before
ft =getFragmentManager().beginTransaction();
line.

try to call ft =getFragmentManager().beginTransaction(); after adding bundle as arguments.

Related

Fragment Crashes on ViewPager's OnPageChangeListener's onPageSelected method

I met a strange thing with ViewPager. I googled but do not find anything useful.
So I post what I have met here, maybe later someone get the same problem, or maybe luckily some genius guys can solve it.
The situation shows as following:
There are two page in the demo application.
HomeActivity is the main page, and there is a viewpager in it. The viewpager have five fragments(Class PlusOneFragment) in it.
In the fagment, there are two textviews. In the onCreateView method we assign one TextView to mValueTv field.
AboutActivity is the other page used to trigger a application crash. Beacause I have used UncaughtExceptionHandler to catch exception
in a custom Application class, which inherit from android.app.Application. So then application will goto the HomeActivity.
But when crashing, Then something sucks. The applcation crashes again.
That really bugged me.
In the HomeActivity, the viewpager has a ViewPager.OnPageChangeListener.
When its page changed, a methond of the specific position's fragment will be invoked in the onPageSelected method.
The method will set fragment mValueTv's value. In normal situation, it works fine, but when it comes to crash, the method throws a java.lang.NullPointerException exception.
05-06 21:37:24.392 17120-17120/com.rxread.viewpagerissue E/MessageQueue-JNIļ¹• java.lang.NullPointerException
at com.rxread.viewpagerissue.PlusOneFragment.onPageSeleted(PlusOneFragment.java:49)
at com.rxread.viewpagerissue.HomeActivity$1.onPageSelected(HomeActivity.java:33)
at android.support.v4.view.ViewPager.scrollToItem(ViewPager.java:571)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:555)
at android.support.v4.view.ViewPager.onTouchEvent(ViewPager.java:2022)
at android.view.View.dispatchTouchEvent(View.java:7725)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2212)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2242)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1536)
at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2190)
at android.view.View.dispatchPointerEvent(View.java:7905)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4009)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3888)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3499)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3575)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3632)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3499)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5657)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5637)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5608)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5815)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:138)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:5081)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
at dalvik.system.NativeStart.main(Native Method)
Because there were too much code, so I packed them. The demo link is .
I really hope someone can help me.
Thanks very much.
HomeActivity
public class HomeActivity extends ActionBarActivity {
ViewPager mViewpager;
BaseTabHostPagerAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mViewpager= (ViewPager) this.findViewById(R.id.home_ivp);
mViewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener(){
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
Object object=mAdapter.getItem(i);
if(object instanceof PlusOneFragment){
((PlusOneFragment)object).onPageSeleted(i);
}
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
mAdapter=new BaseTabHostPagerAdapter(getSupportFragmentManager());
mViewpager.setAdapter(mAdapter);
mAdapter.addPager("new 1", PlusOneFragment.newInstance("new 1"));
mAdapter.addPager("new 2",PlusOneFragment.newInstance("new 2"));
mAdapter.addPager("new 3",PlusOneFragment.newInstance("new 3"));
mAdapter.addPager("new 4", PlusOneFragment.newInstance("new 4"));
mAdapter.addPager("new 5", PlusOneFragment.newInstance("new 5"));
mAdapter.notifyDataSetChanged();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_home, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
AboutActivity.actionTo(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
AboutActivity
public class AboutActivity extends ActionBarActivity {
public static void actionTo(Context context){
Intent intent=new Intent(context,AboutActivity.class);
context.startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
TextView mClickToCrash= (TextView) findViewById(R.id.about_to_crash_tv);
mClickToCrash.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int exception=2-2;
int a=3/exception;
Toast.makeText(AboutActivity.this, "GO EXCEPTION" + a, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_about, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
PlusOneFragment
public class PlusOneFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private String mParam1;
private TextView mValueTv;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #return A new instance of fragment PlusOneFragment.
*/
// TODO: Rename and change types and number of parameters
public static PlusOneFragment newInstance(String name) {
PlusOneFragment fragment = new PlusOneFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, name);
fragment.setArguments(args);
return fragment;
}
public PlusOneFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
}
}
public void onPageSeleted(int position){
mValueTv.setText("onPageSeleted-Value:" +position+"--"+ SystemClock.currentThreadTimeMillis());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_plus_one, container, false);
TextView textView= (TextView) view.findViewById(R.id.fragment_name);
textView.setText(mParam1);
mValueTv= (TextView) view.findViewById(R.id.fragment_value);
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mValueTv.setText("Value:"+ SystemClock.currentThreadTimeMillis());
Toast.makeText(v.getContext(),"Toast",Toast.LENGTH_SHORT).show();
}
});
return view;
}
#Override
public void onResume() {
super.onResume();
}
ViewPagerIssueApplication
public class ViewPagerIssueApplication extends Application{
#Override
public void onCreate() {
super.onCreate();
CrashHandler handler = CrashHandler.getInstance();
handler.init(getApplicationContext());
Thread.setDefaultUncaughtExceptionHandler(handler);
}
}
CrashHandler
public class CrashHandler implements UncaughtExceptionHandler {
private static CrashHandler myCrashHandler;
private Context mContext;
private CrashHandler() {
}
public static synchronized CrashHandler getInstance() {
if (myCrashHandler != null) {
return myCrashHandler;
} else {
myCrashHandler = new CrashHandler();
return myCrashHandler;
}
}
public void init(Context context) {
mContext = context;
}
#Override
public void uncaughtException(Thread arg0, Throwable exception) {
StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace);
System.exit(1);
}
}
BaseTabHostPagerAdapter
public class BaseTabHostPagerAdapter extends FragmentPagerAdapter {
private List<String> names = new ArrayList<String>();
private List<Fragment> fragments = new ArrayList<Fragment>();
public BaseTabHostPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if(position > fragments.size()){
return null;
}
return fragments.get(position);
}
public List<Fragment> getFragmentsList(){
return fragments;
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
if(position > names.size()){
return null;
}
return names.get(position);
}
public void addPager(String tabStr,Fragment fragment) {
if (fragment != null) {
fragments.add(fragment);
names.add(tabStr);
}
}
public void setTab(int location, String tab){
if(location<0||location>names.size()){
return;
}
if(null!=tab){
names.remove(location);
names.add(location, tab);
}
}
}
Finally, with my team leader's help, I found that some fragments were not attached to the HomeActivity When crashing back to HomeActivity.
The onPageSelected method is invoked ahead of onCreateView method.
The solution is doing getActivity null check in PlusOneFragment's onPageSeleted method.
public void onPageSeleted(int position) {
if (getActivity() == null) {
return;
}
mValueTv.setText("onPageSeleted-Value:" + position + "--" + SystemClock.currentThreadTimeMillis());
}

Activate from menu a CountDownTimer animating inside a Fragment

I have a View Pager that contains 2 Fragments which have several Gauges that need to be animated.
I would like to switch on or off the Countdown Timer for animating these gauges, from the app Actionbar menu.
Attached is my code:
Menu Item from FragmentActivity:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
demoItem = menu.findItem(R.id.menu_demo);
demoItem.setChecked(false);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.menu_enabler:
Intent enablerIntent = new Intent();
PackageManager manager = getPackageManager();
try
{
enablerIntent = manager
.getLaunchIntentForPackage("com.openxc.enabler");
enablerIntent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(enablerIntent);
}
catch (Exception e)
{
String packageName = OPENXC_ENABLER;
Uri uri = Uri.parse("market://details?id=" + packageName);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
break;
case R.id.menu_demo:
if (demoItem.isChecked())
{
demoItem.setChecked(false);
// onDemoActivated.activateDemo(false);
}
else
{
demoItem.setChecked(true);
// onDemoActivated.activateDemo(true);
}
break;
case R.id.menu_settings:
break;
case R.id.menu_app_info:
break;
default:
break;
}
return false;
}
}
And the fragment that I animate Fragment:
public class FragmentGaugeCartoon extends Fragment {
public static final String ARG_OBJECT = "object";
public static final String TAG = "GaugeCartoon";
private Context context;
private final Random RAND = new Random();
private GaugeView gauge1;
private GaugeView gauge2;
private GaugeView gauge3;
// getter for returning fragment instance
public static FragmentGaugeCartoon getInstance() {
return new FragmentGaugeCartoon();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// The last two arguments ensure LayoutParams are inflated
// properly.
View rootView = inflater.inflate(R.layout.fragment_gauge_cartoon,
container, false);
gauge1 = (GaugeView) rootView.findViewById(R.id.gauge_view1);
gauge2 = (GaugeView) rootView.findViewById(R.id.gauge_view2);
gauge3 = (GaugeView) rootView.findViewById(R.id.gauge_view3);
gaugeTimer.start();
return rootView;
}
// dountdown timer for the demo
private final CountDownTimer gaugeTimer = new CountDownTimer(30000, 2000) {
#Override
public void onTick(long arg0) {
gauge1.setTargetValue(RAND.nextInt(101));
gauge2.setTargetValue(RAND.nextInt(201));
gauge3.setTargetValue(RAND.nextInt(2000));
}
#Override
public void onFinish() {
gaugeTimer.start();
}
};
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
} else {
}
}
}
Solved.I have implemented a random number chooser.

Android Fragment resume with Loader

I have a fragment (YearsFragment) with a list. If I klick one item a new fragment (EventsFragment) will be executed.
The loader of the new fragment loads a new list. This works.
Now my Problem:
when I go back to the first YearsFragment and klick the same item the EventsFragment loads again. But I will get the old Loader with the old data.
EventsActivity:
public class EventsActivity extends FragmentActivity implements YearsFragment.OnYearSelectedListener, EventsFragment.OnEventSelectedListener{
private boolean screenSizeLarge;
private EventsFragment eventFrag = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.years_events);
// Check whether the activity is using the layout version with the fragment_container FrameLayout (small Display).
if (findViewById(R.id.fragment_container) != null) {
screenSizeLarge = false; //one-pane
YearsFragment firstFragment = new YearsFragment();
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, firstFragment).commit();
}else{
screenSizeLarge = true; //two-pane
}
}
#Override
public void onYearSelected(Years year) {
// The user selected the year from the YearsFragment
if (screenSizeLarge) {
// two-pane layout
// Capture the events fragment from the activity layout
eventFrag = (EventsFragment) getSupportFragmentManager().findFragmentById(R.id.event_fragment);
// Call a method in the EventFragment to update its content
eventFrag.updateEventsView(year);
} else {
//one-pane layout
if(eventFrag == null){
eventFrag = new EventsFragment();
}
Bundle args = new Bundle();
args.putInt("year", Integer.parseInt(year.getYear()));
eventFrag.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, eventFrag);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}}
YearsFragment:
public class YearsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<Years>>{
YearsAdapter adapter;
// The container Activity must implement this interface so the frag can deliver messages
OnYearSelectedListener mCallback;
public interface OnYearSelectedListener {
/** Called by YearsFragment when a list item is selected */
public void onYearSelected(Years year);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onResume() {
super.onResume();
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
adapter = new YearsAdapter(getActivity());
setListAdapter(adapter);
setEmptyText("No Data Here");
setListShown(false);
getLoaderManager().initLoader(0, null, this);
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
mCallback = (OnYearSelectedListener) activity;
} catch (ClassCastException e){
throw new ClassCastException(activity.toString() +
"must implement OnYearSelectedListener");
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCallback.onYearSelected(adapter.getItem(position));
}
//implements Loader
#Override
public Loader<List<Years>> onCreateLoader(int arg0, Bundle arg1) {
Log.i("YearsFragment","YearsFragment.onCreateLoader");
return new YearsLoader(getActivity());
}
#Override
public void onLoadFinished(Loader<List<Years>> arg0, List<Years> data) {
Log.i("YearsFragment","YearsFragment.onLoadFinished");
adapter.setData(data);
if(isResumed()){
setListShown(true);
}else{
setListShownNoAnimation(false);
}
}
#Override
public void onLoaderReset(Loader<List<Years>> arg0) {
Log.i("YearsFragment","YearsFragment.onLoaderReset");
adapter.setData(null);
}}
EventsFragment:
public class EventsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<Events>>{
EventsAdapter adapter;
private int year;
public EventsFragment(){
year = Calendar.getInstance().get(Calendar.YEAR);
}
// The container Activity must implement this interface so the frag can deliver messages
OnEventSelectedListener mCallback;
public interface OnEventSelectedListener {
/** Called by YearsFragment when a list item is selected */
public void onEventSelected(Events event);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
Log.i("EventsFragment","EventsFragment.onActivityCreated");
adapter = new EventsAdapter(getActivity());
setListAdapter(adapter);
setEmptyText("No Data Here");
setListShown(false);
}
#Override
public void onResume() {
super.onResume();
Bundle args = this.getArguments();
if(args != null){
year = args.getInt("year");
}
updateEventsView(year);
// The activity has become visible (it is now "resumed").
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
mCallback = (OnEventSelectedListener) activity;
} catch (ClassCastException e){
throw new ClassCastException(activity.toString() +
"must implement OnEventsSelectedListener");
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCallback.onEventSelected(adapter.getItem(position));
}
public void updateEventsView(Years year) {
this.year = Integer.parseInt(year.getYear());
getLoaderManager().initLoader(this.year, null, this);
}
public void updateEventsView(int year) {
this.year = year;
getLoaderManager().initLoader(this.year, null, this);
}
//Loader
#Override
public Loader<List<Events>> onCreateLoader(int arg0, Bundle arg1) {
Log.i("EventsFragment","EventsFragment.onCreateLoader");
return new EventsLoader(getActivity(),this.year);
}
#Override
public void onLoadFinished(Loader<List<Events>> arg0, List<Events> data) {
Log.i("EventsFragment","EventsFragment.onLoadFinished");
adapter.setData(data);
if(isResumed()){
setListShown(true);
}else{
setListShownNoAnimation(false);
}
}
#Override
public void onLoaderReset(Loader<List<Events>> arg0) {
Log.i("EventsFragment","EventsFragment.onLoaderReset");
adapter.setData(null);
} }
How I should do the resume?
greets Mr.P.

It's impossible to pass data between these two fragment

I'm going insane!!
I don't manage to pass data from a fragment(A) to an another fragment(B).
I read about using a public interface... and it seems to work, but i don't understand how to use this method.
Fragment(A)
package it.anddev.pagertabs;
public class Page1Fragment extends Fragment {
String Str;
OnDataPass dataPasser;
Class Senddata extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
// do something [...]
}
#Override
protected String doInBackground(String... args) {
// do something [...]
dataPasser.onDataPass(result_array.toString());
}
return null;
}
protected void onPostExecute(String file_url) {
// do something [...]
}};
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
dataPasser = (OnDataPass) activity;
}
public interface OnDataPass {
public void onDataPass(String data);
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
// do something [...]
Button Avanti = (Button) view.findViewById(R.id.sendbutton);
Avanti.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//mViewPager.setCurrentItem(1, true);
new Senddata().execute();
}
});
FragmentB
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
if (container == null) {
return null;
}
View view = (LinearLayout)inflater.inflate(R.layout.page2,container,false);
Button mostra = (Button) view.findViewById(R.id.mostrabutton);
// String str = i need to get string from "public void onDataPass"
mostra.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//mViewPager.setCurrentItem(1, true);
Log.d("IT WORKS", str);
}
});
return view;
}
#Override
public void onDataPass(final String data) {
// TODO Auto-generated method stub
Log.d("okkkkkk", "" + data);
}
So finally, how i can get the string from the public void in the fragmentB?
Thanks
Consider my 2 fragments A and B, and Suppose I need to pass data from B to A.
Then create an interface in B, and pass the data to the Main Activity. There create another interface and pass data to fragment A.
Sharing a small example:
Fragment A looks like
public class FragmentA extends Fragment implements InterfaceDataCommunicatorFromActivity {
public InterfaceDataCommunicatorFromActivity interfaceDataCommunicatorFromActivity;
String data;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void updateData(String data) {
this.data = data;
//data is updated here which is from fragment B
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
interfaceDataCommunicatorFromActivity = (InterfaceDataCommunicatorFromActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement InterfaceDataCommunicatorFromActivity");
}
}
}
FragmentB looks like
class FragmentB extends Fragment {
public InterfaceDataCommunicator interfaceDataCommunicator;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// call this inorder to send Data to interface
interfaceDataCommunicator.updateData("data");
}
public interface InterfaceDataCommunicator {
public void updateData(String data);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
interfaceDataCommunicator = (InterfaceDataCommunicator) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement InterfaceDataCommunicator");
}
}
}
Main Activity is
public class MainActivity extends Activity implements InterfaceDataCommunicator {
public InterfaceDataCommunicatorFromActivity interfaceDataCommunicatorFromActivity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void updateData(String data) {
interfaceDataCommunicatorFromActivity.updateData(data);
}
public interface InterfaceDataCommunicatorFromActivity {
public void updateData(String data);
}
}
The Most easiest way is create a static variable in first fragment and use this variable in second fragment.
Use a public interface to pass the String through the Activity that is containing the fragments. Here is simular question and solution with more detail.
Consider 2 fragments A and B and suppose I need to pass data from B to A.
Then create an interface in B, and pass the data to the Activity. From there you can call in A getActivity() to get the information.
Example:
Activity is:
public class MainActivity extends Activity implements InterfaceDataCommunicator {
public static String data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void updateData(String data) {
this.data = data;
}
}
Fragment A:
public class FragmentA extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().data;//receive data
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Fragment B:
class FragmentB extends Fragment {
public InterfaceDataCommunicator interfaceDataCommunicator;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
interfaceDataCommunicator.updateData(/*the String to send*/); //send data
}
public interface InterfaceDataCommunicator {
public void updateData(String data);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
interfaceDataCommunicator = (InterfaceDataCommunicator) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement InterfaceDataCommunicator");
}
}
}

Android AsyncLoader: Share objects between fragmentactivity/fragment

I have a problem regarding with FragmentActivity and mutltiple Fragments inside a ViewPager.
In the FragmentActivity an object is loaded, with a AsyncTask which is used in all the other fragments. I have used the android:configChanges="orientation|keyboardHidden|keyboard" "hack" to make sure the object is only loaded once, even during a screen rotation.
However, now I would to like to display more infromation in landscape modus in one of the Fragments, so now that hack doesn't work.
I've tried implementing a AsyncLoader and the FragmentRetainInstanceSupport from the Android samples. But none of the things work:
1 - I can't get the FragmentRetainInstanceSupport get to work within the ViewPager, when I follow the sample code the onCreate() method isn't called in the worker-fragment
2 - The AsyncLoader crashes during a screen rotation...
Here is my code in which I (tried to) implement the AsyncLoader:
public class TeamActivity extends SherlockFragmentActivity implements LoaderManager.LoaderCallbacks<Response<Team>> {
ViewPager mPager;
PageIndicator mIndicator;
FragmentPagerAdapter mAdapter;
private final int MENU_FOLLOW = Menu.FIRST;
private final int MENU_UNFOLLOW = Menu.FIRST + 1;
Team team = null;
static int team_id;
public Team getTeam(){
return team;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
team_id = this.getIntent().getIntExtra("index", 0);
Log.d("Teamid",""+team_id);
getSupportLoaderManager().initLoader(0, null, this);//.forceLoad();
//getSupportLoaderManager().getLoader(0).startLoading();
//new getTeam().execute();
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(team != null) {
team.getNaam();
SharedPreferences keyValues = this.getSharedPreferences("teams_follow", Context.MODE_PRIVATE);
MenuItem menuItem_volg = menu.findItem(MENU_FOLLOW);
MenuItem menuItem_delete = menu.findItem(MENU_UNFOLLOW);
if(keyValues.contains(String.valueOf(team.getStartnummer()))) {
menuItem_volg.setVisible(false);
menuItem_delete.setVisible(true);
} else {
menuItem_volg.setVisible(true);
menuItem_delete.setVisible(false);
}
}
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0,MENU_UNFOLLOW,Menu.NONE, R.string.ab_verwijderen)
.setIcon(R.drawable.ic_action_delete)
.setVisible(false)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(0,MENU_FOLLOW,Menu.NONE, R.string.ab_volgen)
.setIcon(R.drawable.ic_action_star)
.setVisible(false)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Utils.goHome(getApplicationContext());
break;
case MENU_FOLLOW:
Utils.addFavoTeam(getApplicationContext(), team);
invalidateOptionsMenu();
break;
case MENU_UNFOLLOW:
Utils.removeFavoteam(getApplicationContext(), team.getID());
invalidateOptionsMenu();
break;
}
return super.onOptionsItemSelected(item);
}
class TeamFragmentAdapter extends FragmentPagerAdapter implements TitleProvider {
ArrayList<Fragment> fragments = new ArrayList<Fragment>();
ArrayList<String> titels = new ArrayList<String>();
public TeamFragmentAdapter(FragmentManager fm) {
super(fm);
fragments.add(new TeamInformatieFragment());
titels.add("Informatie");
fragments.add(new TeamLooptijdenFragment());
titels.add("Routetijden");
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public String getTitle(int position) {
return titels.get(position);
}
}
private class getTeam extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
Response<Team> response;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(TeamActivity.this,
"Bezig met laden", "Team wordt opgehaald...", true);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
cancel(true);
Utils.goHome(TeamActivity.this);
}
});
}
#Override
protected Void doInBackground(Void... arg0) {
if(!isCancelled())
response = api.getTeamByID(team_id);
return null;
}
#Override
protected void onPostExecute(Void result) {
if(Utils.checkResponse(TeamActivity.this, response)) {
setContentView(R.layout.simple_tabs);
team = response.getResponse();
mAdapter = new TeamFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
invalidateOptionsMenu();
progressDialog.dismiss();
}
}
}
public static class AppListLoader extends AsyncTaskLoader<Response<Team>> {
Response<Team> response;
public AppListLoader(Context context) {
super(context);
}
#Override public Response<Team> loadInBackground() {
response = api.getTeamByID(team_id);
return response;
}
#Override public void deliverResult(Response<Team> response) {
if (isReset()) {
return;
}
this.response = response;
super.deliverResult(response);
}
#Override protected void onStartLoading() {
if (response != null) {
deliverResult(response);
}
if (takeContentChanged() || response == null) {
forceLoad();
}
}
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
response = null;
}
}
private ProgressDialog progressDialog;
#Override
public Loader<Response<Team>> onCreateLoader(int arg0, Bundle arg1) {
progressDialog = ProgressDialog.show(TeamActivity.this,
"Bezig met laden", "Team wordt opgehaald...", true);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
finish();
}
});
return new AppListLoader(this);
}
#Override
public void onLoadFinished(Loader<Response<Team>> loader, Response<Team> response) {
//Log.d("Loader", "Klaar");
if(Utils.checkResponse(TeamActivity.this, response)) {
team = response.getResponse();
setContentView(R.layout.simple_tabs);
mAdapter = new TeamFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
invalidateOptionsMenu();
progressDialog.dismiss();
}
}
#Override
public void onLoaderReset(Loader<Response<Team>> arg0) {
//Utils.goHome(this);
}
}
Fragment (example):
public class TeamInformatieFragment extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Team team = ((TeamActivity)this.getActivity()).getTeam();
//ERROR ON NEXT LINE AFTER SCREEN ROTATION:
getSherlockActivity().getSupportActionBar().setTitle(team.getNaam());
View view = inflater.inflate(R.layout.team_informatie, container, false);
return view;
}
}
The method is called from the fragments (with getActivity().getTeam()) but after a screen rotation getTeam() returns null;
I think the fragments are calling getTeam() too fast, before the variable team has been initialized(?)
Can you please help me?
Thank you!
This is probably not what you want to hear, but I recommend getting rid of
android:configChanges="orientation|keyboardHidden|keyboard"
It's an ugly hack, and a lot of the newer SDK elements like Loaders will break if you don't handle configuration changes correctly. Let Android handle the config changes, and design your code around that.

Categories

Resources