Check which Activity loads a fragment - android

Is there a way to check which activity loads a fragment from within the fragment? I have a user profile fragment which is loaded from 2 different activities but only one passes a value in, so when getting values from the bundle when the fragment loads from the activity that doesn't pass a value throws a nullpointerexception. Or is there a better way to pass the value into the fragment so the fragment can get the value only when loaded from this specific activity?

You can simply do this check in your fragment:
if(getActivity() instanceof SomeActivity){
//do something
}
You can also cast the getActivity() call if you are sure which Activity it is (and then call methods from that Activity).

You can define two static methods (also known as Static Factory Methods) which returns instances of your Fragment with the parameters you want to pass with bundle like the following code:
private static final String BUNDLE_VALUE_KEY = "value";
#NonNull
public static YourFragment newInstance() {
return new YourFragment();
}
#NonNull
public static YourFragment newInstance(#NonNull String yourValue) {
final YourFragment instance = new YourFragment();
final Bundle args = new Bundle();
args.putString(BUNDLE_VALUE_KEY,yourValue);
instance.setArguments(args);
return instance;
}
In your Activity which you want to pass the value you can use:
final YourFragment fragment = YourFragment.newInstance(value);
getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, fragment)
.commit();
In other Activity you can use:
final YourFragment fragment = YourFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, fragment)
.commit();
And in onCreate method of your Fragment you can check arguments and init your value like the following code:
final Bundle args = getArguments();
if(args != null){
yourValue = args.getString(BUNDLE_VALUE_KEY,null);
}
So if your Fragment is attached to the Activity which passes data you'll have it. If the Fragment is attached to other Activity you'll have the initial value (in the example it's null)
Or you can check the instance of Activity which Fragment gets attached. (Not best practice)
if(getActivity() instanceof YourActivityWhichPassesData){
yourValue = getArguments().getString(BUNDLE_VALUE_KEY,null);
}

Related

Value in the Fragment cannot be shown

I have a typo regarding getting value from bundle and show it in the Fragment.
My song class has two values title and its detail.
private String songTitle;
private String details;
After sending value from bundle in Adapter part, I get it from Detail Part by doing vice versa process. I show it via getSupportFragmentManager feature.
Although the detail page open without any problem, there is no value in Detail part.
Here is my Detail part and Fragment part.
How can I fix it?
Detail Part
if (savedInstanceState == null) {
// Get the selected song position from the intent extra.
int selectedSong =
getIntent().getIntExtra(SongUtil.SONG_ID_KEY, 0);
Log.i(LOG,"selectedSong : " + selectedSong);
// Create instance of the detail fragment and add it to the activity
// using a fragment transaction.
SongDetailFragment fragment =
SongDetailFragment.newInstance(selectedSong);
getSupportFragmentManager().beginTransaction()
.add(R.id.song_detail_container, fragment)
.commit();
}
Detail Fragment
public static SongDetailFragment newInstance (int selectedSong) {
SongDetailFragment fragment = new SongDetailFragment();
// Set the bundle arguments for the fragment.
Bundle arguments = new Bundle();
arguments.putInt(SongUtil.SONG_ID_KEY, selectedSong);
fragment.setArguments(arguments);
return fragment;
}
Link : Project Link
I solve it by defined static methods for list process in which items are inserted

How to get element back on popBackStack( )

I have two fragments: in the first fragment I do it:
ritorno.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
manager.beginTransaction().replace(R.id.content_frame,new SearchFlight()).addToBackStack(null).commit();
}
});
and this works well. In the second I need to return to the first fragment, so I decide to do this:
String s = element.getText().toString(); //I need to return it
FragmentManager manager = getActivity().getSupportFragmentManager();
SearchFragment fragment = new SearchFragment();
manager.popBackStack();
I need to return to the first fragment this String. How could I do it?
Thanks
There are 3 ways
Static Variable : Define public static variable in first fragment, update its value in second fragment.
BroadcastReceiver
EventBus you can even find EventBus tutorial here
pass string to BR or EventBus and you can fetch it in first fragment by defining appropriate method or listener.
Try doing it with a bundle object.
String s = element.getText().toString(); //item to be returned
FragmentManager manager = getActivity().getSupportFragmentManager();
SearchFragment fragment = new SearchFragment();
Bundle bundle = new Bundle();
bundle.putString("key", "value");
fragment.setArguments(bundle);
manager.popBackStack();
And then, in your SearchFragment resolve the bundle like:
Bundle bundle = this.getArguments();
bundle.getString("key");
Do the resolution part of the bundle in your onCreateView of the SearchFragment. Do place a null check on the resolution part of the bundle. If the bundle is not resolved, then the getString("key") method will give a null pointer exception.

how to reload calling fragment with the previous state and set the result got as a callback from the dialog fragment it initiated

This is how my application runs.
The application has several fragments as view pager connecting through main activity. From Second Fragment, I launched custom fragment dialog and upon ok button click inside that fragment dialog, I am fetching the result into main activity. I am using android.support.v4 library.
public class MainActivity extends FragmentActivity implements MyDialog.Communicator {
private static String callBackMessage;
#Override
public Fragment getItem(int pos) {
switch (pos) {
case 0:
return FirstFragment.newInstance();
case 1:
return SecondFragment.newInstance(MainActivity.this);
default:
return ThirdFragment.newInstance();
}
}
#Override
public void onDialogMessage(String callBackMessage) {
MainActivity.callBackMessage = callBackMessage;
}
public static String getCallBackMessage() {
return callBackMessage;
}
This is my MyDialog Fragment class, here I am creating some rows and giving checkboxes to be selected.
private void performOKButtonFunctionality() {
String msg = checkedBoxesCount + "";
communicator.onDialogMessage(msg);
SecondFragment secondFragment = new SecondFragment();
secondFragment.testFunction(row);
dismiss();
}
Now because of my very early days into android and its fragment life cycle, I am calling a method on Second fragment after instantiating it. the row parameter just passes the row number.
Now inside the Second Fragment Class I have some thing like,
public void testFunction(String callBackRow) {
callBackRowNo = Integer.parseInt(callBackRow);
String callBackMessage = MainActivity.getCallBackMessage();
getTableData(callBackMessage + "");
}
In order to save the SecondFragment previous state, I am saving its context by making it static like this,
private static Context activityContext;
public static SecondFragment newInstance(Context context) {
activityContext = context;
SecondFragment f = new SecondFragment();
Bundle b = new Bundle();
f.setArguments(b);
return f;
}
Now doing so, I am able to use my Second Fragment only one time after clicking the ok button from Fragment Dialog. but upon clicking again, the app crashes at this point.
FragmentManager myDialogManager = getActivity().getSupportFragmentManager();
The raised exception is:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.FragmentManager android.support.v4.app.FragmentActivity.getSupportFragmentManager()' on a null object reference
Now, my questions are:
How do we reenter into the oncreate method of the fragment where it just restores its previous state rather than saving it explicitly before launching
fragment dialog.
How does the fragment dialog pass parameter to the fragment which can be used to update the fragment field.
Is there some easy way to achieve this?
Before asking I searched the SO but could not find anything where this scenario was asked or explained.
I am badly stuck here and any solution/direction is much appreciated.
try getChildFragmentManager() instead of getSupportFragmentManager()
when do you make fragment with newInstace, you can put argsments like this.
public static MyFragment newInstance(int value) {
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putInt("value", value);
f.setArguments(args);
return f;
}
it also needs constructor MyFragment()
public MyFragment() {}
get values from args like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (getArguments() != null) {
value = getArguments().getInt("value");
}
return inflater.inflate(R.layout.your_layout, container, false);
}

Send data from activity to fragment

How can we send data from actvity to fragment? The Fragments are configured to actvity by using FragmentPagerAdapter.
Regards
mini.
You can pass a bundle to the fragment on creation with setArguments.
You can create methods to set the data on the Fragment class.
You can perform this by using Bundle
Send data from the activity (or fragment) :
int a = 5;
Bundle args = new Bundle();
args.putInt("INT_DATA_TAG", a);
Fragment fragment = Fragment.newInstance(args);
//Making fragment transaction
Retrieve data in the fragment
int a;
public static Fragment newInstance(Bundle args) {
a = args.getInt("INT_DATA_TAG"); //use a constant for the tag
return new Fragment();
}

Passing an Object from an Activity to a Fragment

I have an Activity which uses a Fragment. I simply want to pass an object from this Activity to the Fragment.
How could I do it?
All the tutorials I've seen so far where retrieving data from resources.
EDIT :
Let's be a bit more precise:
My Activity has a ListView on the left part. When you click on it, the idea is to load a Fragment on the right part.
When I enter this Activity, an Object Category is given through the Intent. This Object contains a List of other Objects Questions (which contains a List of String). These Questions objects are displayed on the ListView.
When I click on one item from the ListView, I want to display the List of String into the Fragment (into a ListView).
To do that, I call the setContentView() from my Activity with a layout. In this layout is defined the Fragment with the correct class to call.
When I call this setContentView(), the onCreateView() of my Fragment is called but at this time, the getArguments() returns null.
How could I manage to have it filled before the call of onCreateView() ?
(tell me if I'm not clear enough)
Thanks
Create a static method in the Fragment and then get it using getArguments().
Example:
public class CommentsFragment extends Fragment {
private static final String DESCRIBABLE_KEY = "describable_key";
private Describable mDescribable;
public static CommentsFragment newInstance(Describable describable) {
CommentsFragment fragment = new CommentsFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(DESCRIBABLE_KEY, describable);
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
mDescribable = (Describable) getArguments().getSerializable(
DESCRIBABLE_KEY);
// The rest of your code
}
You can afterwards call it from the Activity doing something like:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment fragment = CommentsFragment.newInstance(mDescribable);
ft.replace(R.id.comments_fragment, fragment);
ft.commit();
In your activity class:
public class BasicActivity extends Activity {
private ComplexObject co;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_page);
co=new ComplexObject();
getIntent().putExtra("complexObject", co);
FragmentManager fragmentManager = getFragmentManager();
Fragment1 f1 = new Fragment1();
fragmentManager.beginTransaction()
.replace(R.id.frameLayout, f1).commit();
}
Note: Your object should implement Serializable interface
Then in your fragment :
public class Fragment1 extends Fragment {
ComplexObject co;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Intent i = getActivity().getIntent();
co = (ComplexObject) i.getSerializableExtra("complexObject");
View view = inflater.inflate(R.layout.test_page, container, false);
TextView textView = (TextView) view.findViewById(R.id.DENEME);
textView.setText(co.getName());
return view;
}
}
You should create a method within your fragment that accepts the type of object you wish to pass into it. In this case i named it "setObject" (creative huh? :) ) That method can then perform whatever action you need with that object.
MyFragment fragment;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
fragment = new MyFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, detailsFragment)
.commit();
} else {
fragment = (MyFragment) getSupportFragmentManager().findFragmentById(
android.R.id.content);
}
fragment.setObject(yourObject); //create a method like this in your class "MyFragment"
}
Note that i'm using the support library and calls to getSupportFragmentManager() might be just getFragmentManager() for you depending on what you're working with
Get reference from the following example.
1. In fragment:
Create a reference variable for the class whose object you want in the fragment. Simply create a setter method for the reference variable and call the setter before replacing fragment from the activity.
MyEmployee myEmp;
public void setEmployee(MyEmployee myEmp)
{
this.myEmp = myEmp;
}
2. In activity:
//we need to pass object myEmp to fragment myFragment
MyEmployee myEmp = new MyEmployee();
MyFragment myFragment = new MyFragment();
myFragment.setEmployee(myEmp);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.main_layout, myFragment);
ft.commit();
Passing arguments by bundle is restricted to some data types. But you can transfer any data to your fragment this way:
In your fragment create a public method like this
public void passData(Context context, List<LexItem> list, int pos) {
mContext = context;
mLexItemList = list;
mIndex = pos;
}
and in your activity call passData() with all your needed data types after instantiating the fragment
WebViewFragment myFragment = new WebViewFragment();
myFragment.passData(getApplicationContext(), mLexItemList, index);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.my_fragment_container, myFragment);
ft.addToBackStack(null);
ft.commit();
Remark: My fragment extends "android.support.v4.app.Fragment", therefore I have to use "getSupportFragmentManager()". Of course, this principle will work also with a fragment class extending "Fragment", but then you have to use "getFragmentManager()".
To pass an object to a fragment, do the following:
First store the objects in Bundle, don't forget to put implements serializable in class.
CategoryRowFragment fragment = new CategoryRowFragment();
// pass arguments to fragment
Bundle bundle = new Bundle();
// event list we want to populate
bundle.putSerializable("eventsList", eventsList);
// the description of the row
bundle.putSerializable("categoryRow", categoryRow);
fragment.setArguments(bundle);
Then retrieve bundles in Fragment
// events that will be populated in this row
mEventsList = (ArrayList<Event>)getArguments().getSerializable("eventsList");
// description of events to be populated in this row
mCategoryRow = (CategoryRow)getArguments().getSerializable("categoryRow");
If the data should survive throughout the application lifecycle and shared among multiple fragments or activities, a Model class might come into consideration, which has got less serialization overhead.
Check this design example
This one worked for me:
In Activity:
User user;
public User getUser(){ return this.user;}
In Fragment's onCreateView method:
User user = ((MainActivity)getActivity()).getUser();
Replace the MainActivity with your Activity Name.

Categories

Resources