What does getActivity() mean? - android

What does getActivity() mean? I saw in somewhere, they wrote MainActivity.this.startActionMode(mActionModeCallback) instead of getActivity(). could someone explain what this two lines mean?
someView.setOnLongClickListener(new View.OnLongClickListener() {
// Called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});

Two likely definitions:
getActivity() in a Fragment returns the Activity the Fragment is currently associated with. (see http://developer.android.com/reference/android/app/Fragment.html#getActivity()).
getActivity() is user-defined.

getActivity() is used for fragment. For activity, wherever you can use this, you can replace the this in fragment in similar cases with getActivity().

getActivity()- Return the Activity this fragment is currently associated with.

I to had a similar doubt what I got to know was getActivity() returns the Activity to which the fragment is associated.
The getActivity() method is used generally in static fragment as the associated activity will not be static and non static member cannot be used in static member.

Related

Trying to call a fragment method from parent activity but the method is not being resolved

I tried the solution here:
Calling a Fragment method from a parent Activity
But it didn't work for me.
I have this method in my fragment
public void showbutton()
{
sup.setEnabled(true);
}
and I'm using this in the parent activity
Fragment fragment = (Fragment) getFragmentManager().findFragmentById(R.id.fragment);
fragment.showbutton();
I'm sure it's a silly mistake, I'm still new to Android so forgive me.
Use callback to communicate from fragment to Activity.
public interface UserAction {
void showButton();
}
In the Fragment implement the Interface
#Override
public void showButton() {
sup.setEnabled(true);
}
Then in your activity just call
UserAction mUserAction = getFragmentManager().findFragmentById(R.id.fragment);
mUserAction.showButton();
Firstly, make sure you are accessing the correct FragmentManager, verify that you need to call either getFragmentManager() or getSupportFragmentManager().
Secondly, you should cast the Fragment to your type. That is,
MyFragment fragment = (MyFragment) getFragmentManager().findFragmentById(R.id.fragment);
fragment.showbutton();
I think you should typecast using Fragment Name.
i.e
YourFragment fragment = (YourFragment) getFragmentManager().findFragmentById(R.id.fragment);
fragment.showbutton();
This issue is regarding to fragment life cycle. You are trying to invoke method of fragment which is closed by android OS. You need to create bool in your fragment and set that to false normally but when you need to show button just create that fragment and load that and update your bool to true.Later on check if that bool is true enable your button else disable it. Happy Coding!

How can I know that onCreateView has been called from an outer class?

I'm really curious about how to determine (from an outer class) if a fragment's onCreateView() has already been called. I have searched for similar questions but found none.
For instance, is fragment.isAdded() a good indicator?
My first thought was simply fragment.getView() != null, but I'm not 100% sure it would be reliable as it seems, and I'm also slightly reluctant to use it (for no particular reason, I just tend to avoid nullity checks). I would be happy to find a workaround. Suggestions I had:
isAdded()
Return true if the fragment is currently added to its activity.
This line is quite ambiguous in my opinion; added is not attached, but neither created. It might refer to FragmentTransaction.add() (which is semantically wrong because you can have <fragment>s stuck in your layout without having to call add or replace).
Still, FragmentTransaction.add() documentation gives no info nor makes you think added -> created. I'd say no.
isVisible()
Return true if the fragment is currently visible to the user. This means it: (1) has been added, (2) has its view attached to the window, and (3) is not hidden.
Looks good, in the sense that isVisible() -> isCreated, but the third option makes it isCreated != isVisible. I just think of fragments inside a view pager: not all are visible, but the fragments near the currently visible fragment are added, created and alive, you can call methods on them. But for them, isVisible() == false. This is kind of too strict.
isInLayout()
Return true if the layout is included as part of an activity view
hierarchy via the < fragment> tag. This will always be true when
fragments are created through the < fragment> tag, except in the case
where an old fragment is restored from a previous state and it does
not appear in the layout of the current state.
I don't think this applies here.
getView() != null
Returns
The fragment's root view, or null if it has no layout.
This still looks the one and only solution. I'd just like a confirmation about that.
Implement a callback
..to be called onCreateView() or, better, onViewCreated(). But:
I don't need to call something as soon as the fragment is created (why would you need that?), I need something to check at a given time;
One should define the opposite, say, onViewNotAvailableAnymore(), to make the check meaningful at all times;
I don't see how this would be different, or better, than getView != null.
Does Fragment.isAdded() imply that onCreateView has been called?
NO!! NO!! pause NOOOOOOO00000000000!!!!!
SIr
Fragment.isAdded() is a notification that your Fragment has been added to your Activity, end of story.
The add() method in FragmentTransaction has 3 different methods, all adds Fragment to an Activity ,and, two goes further to create your Fragments View and attach it to a Parent ViewGroup by the aid of LayoutInflater provided your first parameter is not 0 (id != 0)
To check if onCreateView() has been called you need to override onViewCreated().
getView() will always return null unless onCreateView() is done
your solution is check Fragment.isVisible()
FYI: There is nothing wrong that i see with the documentation. Its pretty clear sir.
Hope i am lucid Sir
Assuming
you're not interested in whether the Fragment is visible
you want to know only if the onCreateView(...) method has been called by the Android framework
you need to use existing Fragment API methods to find out
then use
getView() != null
provided that you inflate the layout and return the View inside onCreateView(...) .
A non-Fragment-API approach is to add a callback in onCreate(...), which you then call in onCreateView() or later (in lifecycle) method.
It can be done using interface. make an interface OnCreateViewListerner
public interface OnViewCreatedListener
{
void onCreateCalled();
}
create a static object of OnViewCreatedListener in your Fragment and initialize it within in your Outer class and Outer class implement this interface like
public class CustomClass implements OnViewCreatedListener{
#Override
public void onCreateCalled() {
}
public void initializeInterface()
{
FragmentTest.listerner = this;
}
.....
}
then override your onCreateView() method and write this
public class FragmentTest extends Fragment{
public static OnViewCreatedListener listerner;
View mView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// if (container == null)
if(listerner!= null)
{
listerner.onCreateCalled();
}
mView = inflater.inflate(R.layout.fragment_product, container, false);
return mView;
}
}
Hope this will help you.
Please consider this approach as I did same like this:
Define an Interface with in your Fragment say:
public Interface IDoSomething{
void intimateAfterOnCreateView();
}
Now, call this method with in onStart() of a fragment as according to life cycle this method will be called after the onCreateView().
Outside from this fragment just implement IDoSomething and you will get an overrided method(intimateAfterOnCreateView()) automatically.
Now this method's execution will show that onCreateView() has been called.
I just want to share my knowledge, may be it helps.
If isAdded() on a Fragment returns true, it doesn't mean that the onCreateView() has been called. In fact, isAdded returns true even during the onAttach callback, that is called before the onCreate().
I would go with extending the Fragment class and adding a public method that you can use to reach from outer of your custom Fragment Class.
When the onCreateView() is called, you can set a boolean value to true and according to your architecture, you can set it to false back again when it's in onPause() or onStop() or onDestroyView() or onDestroy() or onDetach(), up to you.
I don't think the methods you mentioned in your question will provide you exactly what you need.
How can I know that onCreateView has been called from an outer class?
You need to create interface inside your fragment and implement it in the container activity (let's say MainActivity).
1. First create an interface inside your fragment:
// Container activity must implement this interface
public interface OnCreateViewCalledListener {
void OnCreateViewCalled(String someData);
}
2. Next implement the interface inside your container activity (lets say it is MainActivity) and call it's method:
public class MainActivity extends AppCompatActivity implements
YourFragment.OnCreateViewCalledListener {
...
#Override
public void OnCreateViewCalled(String someData) {
Toast.makeText(MainActivity.this, "OnCreateView was called and passed " + someData)
}
3. Then you need to check if MainActivity implements interface callbacks (this step is crucial to make it work properly):
//Using onAttach method to check that activity has implemented callbacks
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Make sure that container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnCreateViewCalledListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnCreateViewCalledListener");
}
}
4. And finally you need to trigger the callback inside onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mCallback.OnCreateViewCalled("Some useful data");
...
}
That's it!
EDIT:
To let other class know that onCreateView was called, please use the onCreateViewCalled() callback inside the MainActivity (e.g. use another interface to trigger callback in other class).
Also it is not mandatory to pass data into the OnCreateViewCalled()
Does Fragment.isAdded() imply that onCreateView has been called?
YES
isAdded() Return true if the fragment is currently added to its activity. (Implicitly onCreateView() has been called).

Android tired with fragment

i have extended a fragment named 'DetailFragment' from home activity.But i cannot access the functions of activity in fragment class,like animation,tablayout,and any other functions which i did in activity.But when i change fragment to fragment activity every error getting cleared,But i need fragment only.
Here is my code
public class DetailFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle args) {
View view = inflater.inflate(R.layout.activity_detail, container, false);
getting error # 'loadanimation'
Animation animationFadeIn = AnimationUtils.loadAnimation(this,R.anim.fadein);
Animation animationFadeOut = AnimationUtils.loadAnimation(this,R.anim.fadeout);
getting error # 'onTouchEvent'
public boolean onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
return view;
}
}
i need to know that is it possible to work on fragment like we works on activity or is there any functions like 'getActivity' method to access activity class,and how i can implement it. that's enough. thank you in advance programmers..
Actually what you have to do is:
you have to replace all the "this" with "getActivity()"
In activity class pointing to "this" means pointing to the context of the activity.
But as your fragment is nothing but a part of the container of parent activity. In the fragment if you keep "this" it will point to the context of the fragment (not points to the parent activity). thats why you are getting error.
Your problem should be solved by:
Animation animationFadeIn = AnimationUtils.loadAnimation(getActivity(),R.anim.fadein);
Animation animationFadeOut = AnimationUtils.loadAnimation(getActivity(),R.anim.fadeout);
But i cannot access the functions of activity in fragment class,like animation,tablayout,and any other functions which i did in activity.
You can the activity method using getActivity() method
((MyActivityClassName)getActivity()).myPublicMethod();

Behavior of Fragments in Android

I cannot find anything on this... I am wondering when I have a fragment within an activity why I can't call certain things such as getPackageName(), and getContentResolver()?
Call from a non static function inside the fragment, after it attaches to the activity.
getActivity().getPackageName();
getActivity().getContentResolver();
As your commenter stated, these are not fragment functions, you have to get the contextWrapper instance.
Because as per this documentation, the methods you mentioned are methods of the Context class. Activity is a subclass of Context, therefore it has these methods available. Fragment, however, is not. There are 2 ways to get hold of these methods from a fragment:
First option: After your fragment has been attached (it's onAttach() method has been called) you can use the getActivity() method to get the activity that it has been attached to. Then you can use getPackageName() and getContentResolver(). Such as this: getActivity().getPackageName(). To be extra safe, you might want to do:
Activity myActivity = getActivity();
if (myActivity != null)
{
myActivity.getPackageName();
myActivity.getContentResolver();
}
else
{
//deal with the null problem
}
Second option: In the onCreateView() method, your fragment won't yet be attached so you can't use the above method. You may use the LayoutInflater to get a View. Then call getContext() on the view. Such as this:
View myView = inflater.inflate(R.layout.my_fragment_layout, container, false);
myView.getContext().getPackageName();
myView.getContext().getContentResolver();

FragmentPagerAdapter doesn't recreate Fragments on orientation change?

I have a ViewPager (extends FragmentPagerAdapter) which holds two Fragments. What I need is just refresh a ListView for each Fragment when I swipe among them. For this I have implemented ViewPager.OnPageChangeListener interface (namely onPageScrollStateChanged). In order to hold references to Fragments I use a HashTable. I store references to Fragments in HashTable in getItem() method:
#Override
public Fragment getItem(int num) {
if (num == 0) {
Fragment itemsListFragment = new ItemsListFragment();
mPageReferenceMap.put(num, itemsListFragment);
return itemsListFragment;
} else {
Fragment favsListFragment = new ItemsFavsListFragment();
mPageReferenceMap.put(num, favsListFragment);
return favsListFragment;
}
}
So when I swipe from one Fragment to another the onPageScrollStateChanged triggers where I use the HashTable to call required method in both Fragments (refresh):
public void refreshList() {
((ItemsListFragment) mPageReferenceMap.get(0)).refresh();
((ItemsFavsListFragment) mPageReferenceMap.get(1)).refresh();
}
Everything goes fine until orientation change event happens. After it the code in refresh() method, which is:
public void refresh() {
mAdapter.changeCursor(mDbHelper.getAll());
getListView().setItemChecked(-1, true); // The last row from a exception trace finishes here (my class).
}
results in IllegalStateException:
java.lang.IllegalStateException: Content view not yet created
at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
at ebeletskiy.gmail.com.passwords.ui.ItemsFavsListFragment.refresh(ItemsFavsListFragment.java:17)
Assuming the Content view is not created indeed I set the boolean variable in onActivityCreated() method to true and used if/else condition to call getListView() or not, which shown the activity and content view successfully created.
Then I was debugging to see when FragmentPagerAdapter invokes getItem() and it happens the method is not called after orientation change event. So looks like it ViewPager holds references to old Fragments. This is just my assumption.
So, is there any way to enforce the ViewPager to call getItem() again, so I can use proper references to current Fragments? May be some other solution? Thank you very much.
Then I was debugging to see when FragmentPagerAdapter invokes getItem() and it happens the method is not called after orientation change event. So looks like it ViewPager holds references to old Fragments.
The fragments should be automatically recreated, just like any fragment is on an configuration change. The exception would be if you used setRetainInstance(true), in which case they should be the same fragment objects as before.
So, is there any way to enforce the ViewPager to call getItem() again, so I can use proper references to current Fragments?
What is wrong with the fragments that are there?
I've spent some days searching for a solution for this problem, and many points was figured out:
use FragmentPagerAdapter instead of FragmentStatePagerAdapter
use FragmentStatePagerAdapter instead of FragmentPagerAdapter
return POSITION_NONE on getItemPosition override of FragmentPagerAdapter
don't use FragmentPagerAdapter if you need dynamic changes of Fragments
and many many many others...
In my app, like Eugene, I managed myself the instances of created fragments. I keep that in one HashMap<String,Fragment> inside some specialized class, so the fragments are never released, speeding up my app (but consuming more resources).
The problem was when I rotate my tablet (and phone). The getItem(int) wasn't called anymore for that fragment, and I couldn't change it.
I really spent many time until really found a solution, so I need share it with StackOverflow community, who helps me so many many times...
The solution for this problem, although the hard work to find it, is quite simple:
Just keep the reference to FragmentManager in the constructor of FragmentPagerAdapter extends:
public class Manager_Pager extends FragmentPagerAdapter {
private final FragmentManager mFragmentManager;
private final FragmentActivity mContext;
public Manager_Pager(FragmentActivity context) {
super( context.getSupportFragmentManager() );
this.mContext = context;
this.mFragmentManager = context.getSupportFragmentManager();
}
#Override
public int getItemPosition( Object object ) {
// here, check if this fragment is an instance of the
// ***FragmentClass_of_you_want_be_dynamic***
if (object instanceof FragmentClass_of_you_want_be_dynamic) {
// if true, remove from ***FragmentManager*** and return ***POSITION_NONE***
// to force a call to ***getItem***
mFragmentManager.beginTransaction().remove((Fragment) object).commit();
return POSITION_NONE;
}
//don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}
#Override
public Fragment getItem( int position ) {
if ( position == MY_DYNAMIC_FRAGMENT_INDEX){
Bundle args = new Bundle();
args.putString( "anything", position );
args.putString( "created_at", ALITEC.Utils.timeToStr() );
return Fragment.instantiate( mContext, FragmentClass_of_you_want_be_dynamic.class.getName(), args );
}else
if ( position == OTHER ){
//...
}else
return Fragment.instantiate( mContext, FragmentDefault.class.getName(), null );
}
}
Thats all. And it will work like a charm...
You can clear the saved instance state
protected void onCreate(Bundle savedInstanceState) {
clearBundle(savedInstanceState);
super.onCreate(savedInstanceState, R.layout.activity_car);
}
private void clearBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
savedInstanceState.remove("android:fragments");
savedInstanceState.remove("android:support:fragments");
savedInstanceState.remove("androidx.lifecycle.BundlableSavedStateRegistry.key");
savedInstanceState.remove("android:lastAutofillId");
}
}

Categories

Resources