String doesn't update when passed to different Fragment? - java

I'm trying to send two strings from Fragment A to Fragment B. Currently, i've implemented an interface listener like this...
Fragment A Method:
String arrayTitle1 = arrayList.get(Index).get("ArrayTitle1");
String arrayTitle2 = arrayList.get(Index).get("ArrayTitle2");
((TextFooterListener) getActivity()).onTextFooterListener(arrayTitle1, arrayTitle2);
I pass these strings to the Activity which sends them to Fragment B like this...
Activity:
#Override
public void onTextFooterListener(String arrayTitle1, String arrayTitle2) {
FragmentB.arrayTitle1 = arrayTitle1;
FragmentB.arrayTitle2 = arrayTitle2;
}
Fragment B:
They are then received and stored in Fragment B as public strings.
public String arrayTitle1;
public String arrayTitle2;
And in the onCreateView of Fragment B, i try to assign these strings.
arrayTitle1Footer.setText(arrayTitle1);
arrayTitle2Footer.setText(arrayTitle2);
But unfortunately, whenever Fragment A's method gets called, the onTextFooterListener doesn't seem to update the strings.
Any suggestions?

You change the values in Fragment B but never actually reassign the new values into the TextViews.
Change
#Override
public void onTextFooterListener(String arrayTitle1, String arrayTitle2) {
FragmentB.setTitles(arrayTitle1, arrayTitle2);
}
And in Fragment B :
public void setTitles(String title1, String title2) {
arrayTitle1 = title1;
arrayTitle2 = title2;
arrayTitle1Footer.setText(arrayTitle1);
arrayTitle2Footer.setText(arrayTitle2);
}

There is a mechanism you need to use to pass data to a Fragment. Please consider the following approach:
#Override
public void onTextFooterListener(String arrayTitle1, String arrayTitle2) {
Bundle data = new Bundle();
data.putString("array1", arrayTitle1);
data.putString("array2", arrayTitle2);
FragmentB b = FragmentB();
b.setArguments(data);
}
Then in your onCreateView of FragmentB:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
arrayTitle1 = getArguments().getString("array1");
arrayTitle2 = getArguments().getString("array2");
arrayTitle1Footer.setText(arrayTitle1);
arrayTitle2Footer.setText(arrayTitle2);
return inflater.inflate(R.layout.fragment, container, false);
}

Related

How do I update my Fragment after data modification in my activity (SQLite)?

I have a ListView in a Fragment that is populated when the app starts.
I put a ParcelableArrayList in a Bundle in my newInstance method, and I get it back in my OnCreateView after passing the ArrayList in the newInstance method in my Activity (which is the data read from the SQLite database).
This part works, as I display my data in my Fragment correctly.
I implemented a button that removes all data from the table, and I would now like to update my view after I cleaned the table.
The remove all button is handled in my main activity where I call my database handler to empty the table.
What is the best way to do that ? Here are the parts of the code that seem relevant to me :
My Fragment class :
public class MainFragment extends Fragment {
public static final String RECETTES_KEY = "recettes_key";
private List<Recette> mRecettes;
private ListView mListView;
public MainFragment() {
// Required empty public constructor
}
public static MainFragment newInstance(List<Recette> r) {
MainFragment fragment = new MainFragment();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(RECETTES_KEY, (ArrayList<? extends Parcelable>) r);
fragment.setArguments(bundle);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRecettes = getArguments().getParcelableArrayList(RECETTES_KEY);
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
configureListView();
}
// Configure ListView
private void configureListView(){
this.mListView = getView().findViewById(R.id.activity_main_list_view);
RecetteAdapter adapter = new RecetteAdapter(getContext(), mRecettes);
mListView.setAdapter(adapter);
}
}
Relevant parts from my Main acivity :
This is in my OnCreate method :
mDatabaseHandler = new DatabaseHandler(this);
mRecettes = mDatabaseHandler.readRecettes();
mDatabaseHandler.close();
This is in the method I use to show a fragment :
if (this.mMainFragment == null) this.mMainFragment = MainFragment.newInstance(mRecettes);
this.startTransactionFragment(this.mMainFragment);
Let me know if I should add more of my code, this is my first time posting :)
Lucile
In your R.layout.fragment_main, you can add an id to the root view, say with android:id#+id/fragment_root
And whenever you want to change the fragment view:
In activity:
MainFragment fragment = (MainFragment) getSupportFragmentManager().getFragmentById(R.id.fragment_root);
fragment.updateList(mRecettes);
And then create the new method updateList() in your MainFragment
public void updateList(List<Recette> recettes) {
mRecettes.clear();
mRecettes.addAll(recettes);
configureListView();
}
Also you can tag your fragment when you add it to your transaction instead of using its id, and then use getSupportFragmentManager().getFragmentByTag()

Unable to send Strings from one Fragment to another via Bundles

I am trying to send two strings via a bundle to the next fragment but the app crashes even before I get to the first fragment.
I get this error in the second fragment:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.guessit, PID: 22360
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at com.example.android.guessit.GameFlow.FragmentAnswer1.onCreateView(FragmentAnswer1.java:125)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1696)
at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:299)
at androidx.fragment.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:259)
at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
at androidx.viewpager.widget.ViewPager.setCurrentItemInternal(ViewPager.java:669)
at androidx.viewpager.widget.ViewPager.setCurrentItemInternal(ViewPager.java:631)
at androidx.viewpager.widget.ViewPager.setCurrentItem(ViewPager.java:612)
at com.example.android.guessit.GameFlow.GameActivity.setViewPager(GameActivity.java:152)
at com.example.android.guessit.GameFlow.FragmentOneCategory$6.onClick(FragmentOneCategory.java:190)
at android.view.View.performClick(View.java:7352)
at android.view.View.performClickInternal(View.java:7318)
at android.view.View.access$3200(View.java:846)
at android.view.View$PerformClick.run(View.java:27800)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7050)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
I know that this means that the string value that I am trying to receive in the second fragment means that there is no value for that string but I don't know where the problem here is because the strings I am trying to send are not null.
This is the code I am using for the bundle in the first fragment (using this in onCreatView):
FragmentAnswer1 frag1 = new FragmentAnswer1();
Bundle args = new Bundle();
args.putString("question_1", question);
args.putString("answer_1", answer);
frag1.setArguments(args);
getFragmentManager().beginTransaction().add(R.id.container, frag1).commit(); // there is a message that says that "beginTransaction" may produce a nullPointer
Here is the code to receive the strings in the second fragment (currently also in onCreateView)
question = getArguments().getString("question_1"); // error is in this line
answer = getArguments().getString("answer_1");
question1.setText(question);
rightAnswer.setText(answer);
I already tried to move the above code into the onStartmethod but I still get the same error. I also tried using this solution but its not working for me. I did not find any other solution or method on how to resolve the problem.
Please let me know if you need more informations. Any help is much appreciated!
I have now found the correct way to send data from one Fragment to another while having a ViewPager. We have to use a ViewModel.
First we have to create a ViewModel, in this case our goal is to send a String from Fragment 1 to Fragment 2. Here is the code for the ViewModel with Getter and Setter method for the String:
public class ViewModelString extends ViewModel {
private MutableLiveData<String> mString = new MutableLiveData<>();
public MutableLiveData<String> getmString() {
return mString;
}
public void setmString(MutableLiveData<String> mString) {
this.mString = mString;
}
}
Then in Fragment 1 from where we want to sent the string we need to first initialize the ViewModel in onCreate.
public class Fragment1 extends Fragment {
private ViewModelString viewModel;
public Fragment1() {
// Required empty public constructor
}
public static Fragment1 newInstance() {
return new Fragment1();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialize ViewModel here
viewModel = ViewModelProviders.of(requireActivity()).get(ViewModelString.class);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
String hello = "hello";
viewModel.setmString(hello);
}
}
Then in the second Fragment we also have to first initialize the viewModel and then create an observer. Here we then take the String that is stored in the ViewModel and set a TextView to its value:
public class Fragment2 extends Fragment {
private ViewModelString viewModel;
public Fragment2() {
// Required empty public constructor
}
public static Fragment2 newInstance() {
return new Fragment2();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialize ViewModel here
viewModel = ViewModelProviders.of(requireActivity()).get(ViewModelString.class);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
TextView textView = findViewById(R.id.yourTextViewId);
// Gets the string
viewModel.getmString().observe(requireActivity(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
}
...
}
I hope this helps anyone! Please feel free to edit my post.
Use Bundle to send String:
//Put the value
Bundle args = new Bundle();
args.putString("YourKey", "YourValue");
YourFragmentName ldf = new YourFragmentName ();
ldf.setArguments(args);
//Inflate the fragment
getActivity().getSupportFragmentManager().beginTransaction().add(R.id.container, ldf).commit();
In onCreateView of the new Fragment:
//Retrieve the value
Bundle bundle = this.getArguments();
if (bundle != null) {
String value = bundle.getString("YourKey");
}
Use a Bundle. Here's an example:
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt("Key", "value");
fragment.setArguments(bundle);
fragmentManager.beginTransaction().replace(R.id.container, frag1).commit()
Bundle has put methods for lots of data types. See this
Then in your Fragment, retrieve the data in onCreate() method like:
Bundle bundle = this.getArguments();
if (bundle != null) {
int myInt = bundle.getString(Key);
}
try this.
var fragment: MainFragment =MainFragment()
val args = Bundle()
args.putString("question_1", "My question")
args.putString("answer_1", "My answer")
fragment.setArguments(args)
fragmentManager.beginTransaction().add(R.id.fragment_content, fragment).commit()

How to add an Item Click Listener in `RecyclerView.Adapter' using CardView Item

How can I add an Item Click Listener for my `RecyclerView.Adapter'
when the user clicks on the Card View item, Data sent to the PostContent Fragment?
Also, is it possible to send the data from this adapter to the new fragment using intent?
Please note my code:
public class PostDataAdapter extends RecyclerView.Adapter<PostDataAdapter.MyViewHolder> {
private List<PostData> PostDataList ;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView vPostContent, vPostDate, vPostAuthor, vPostTitr,VPostLikes,VPostViews;
public ImageView vPostPhoto;
public MyViewHolder(View v) {
super(v);
vPostContent = v.findViewById(R.id.PostContentTv);
vPostDate = v.findViewById(R.id.PostDateTv);
vPostAuthor = v.findViewById(R.id.PostAuthorTv);
vPostTitr = v.findViewById(R.id.PostTitrTv);
vPostPhoto = v.findViewById(R.id.PostPhoto);
VPostLikes=v.findViewById(R.id.PostLikeTv);
VPostViews=v.findViewById(R.id.PostViewTv);
}
}
public PostDataAdapter(List<PostData> postDataList) {
PostDataList = postDataList;
}
#Override
public PostDataAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_posts, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.vPostDate.setText(PostDataList.get(position).getPostDate());
holder.vPostTitr.setText(PostDataList.get(position).getPostTitr());
holder.vPostContent.setText(PostDataList.get(position).getPostContent());
holder.vPostAuthor.setText(PostDataList.get(position).getPostAuthor());
holder.VPostViews.setText(PostDataList.get(position).getPostViews());
holder.VPostLikes.setText(PostDataList.get(position).getPostLikes());
new DownloadImageTask(holder.vPostPhoto).execute(PostDataList.get(position).getImgpost());
}
#Override
public int getItemCount() {
return PostDataList.size();
}
}
To add a ItemCLickListener for RecyclerView, you need to implement a custom Interface which the Fragment will implement. When the list item is clicked, then the callback function of the interface is called.
CustomItemClickListener.java:
public CustomItemClickListener {
void onItemClick(Object data);
}
Just add these to the PostDataAdapter:
PostDataAdapter.java:
private CustomItemClickListner clickListener;
public PostDataAdapter(CustomItemClickListner listener, List<PostData> postDataList) {
PostDataList = postDataList;
clickListener = listener
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.vPostCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Modify the parameters of the function according to what you want to send to the fragment
// As soon as this is called, the `onItemClick` function implemented in the Fragment gets called.
clickListener.onItemClick(Object data);
}
});
}
Fragment.java:
CustomFragment extends Fragment implements CustomItemClickListener {
public CustomFragment() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view;
PostDataAdapter adapter = new PostDataAdapter(this, new ArrayList<PostData>)
return view;
}
#Override
public void onItemClick(Object data) {
// Handle the data sent by the adapter on item click
}
}
Yu cand send data from Adapter to a Fragment with Intent:
Fragment fragment = new tasks();
FragmentManager fragmentManager = context.getSupportFragmentManager(); // this is the context of the Activity
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Bundle bundle=new Bundle();
bundle.putString("name", "Osmar Cancino"); //key and value
//set Fragmentclass Arguments
fragment.setArguments(bundle);
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Although my suggestion is to manage the flow of screens from the parent activity, and manage the data through a Callback, even with a custom Interface
There are two ways you can do this.
Write recyclerview.onitem touchlistener(...). Then consume that event in your fragment. As you will get item position inside touchlistener callback, you can take out data from your list directly from the list you passed to your adapter (Assuming you have list reference outside in your fragment.)
Oobserver pattern.
Define a functional interface (one callback method with required parameters of the data you want to pass) implement inside your fragment. Send its reference with the constructor of adapter. Then Store reference in a interface type variable inside adapter. Write click listener on card. And on the card click, invoke method using interface type variable.
Intents can be used to send data to new activities but not fragments You'd have to use the Fragment Manager and attach a bundle to it to send data. You can refer to the documentation here on how to do so:
https://developer.android.com/training/basics/fragments/communicating#Deliver
To handle click on cards, you can create a listener when you create PostDataAdapter. Refer to the following link for a simple example:
https://stackoverflow.com/a/40584425/4260853
for adding click item for a Cardview, you can find the Cardview in MyViewHolder class by id and in onBindViewHolder set a click listerner for it like the following
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.vPostCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//write your codes here
}
});
}
if you have an intent that you want to send it's data to a fragment, you can get the intent data and send them with bundle to your fragment. for example do something like the following.
Bundle bundle = new Bundle();
bundle.putString("your_key",intent.getStringExtra("your_item_key_in_intent"));
and after that send bundle to your fragment with
fragment.setArguments(bundle);

Pass Json Object from ViewHolder to Fragment

I have a RecyclerView and a Fragment. I want to pass a JSONObject from RecyclerView to Fragment. So, I created an Interface and implemented it on Fragment and on RecyclerView. I initialized the variable and access the method in the fragment passing the JSONObject to it, however I am getting a NPE when trying to access the method:
public class ProductResultsListFragment extends Fragment implements ProductResultAdapterInterface{
//code here
#Override
public void showResultsInMap(JSONObject mapObject)
{
openMapFragment(mapObject);
}
In my RV class I have the following:
public class ProductSearchAdapter extends RecyclerView.Adapter<ProductSearchAdapter.ViewHolder> {
public ProductResultAdapterInterface mProductResultsListener;
.....
if (mapObjects.length()>0)
{
mProductResultsListener.showResultsInMap(mapObjects);
}
The if statement is inside my viewHolder in my RecyclerView class but the instance is made public.
I have tried casting my mProductResultsListener but dont know what class to cast it into.
public ProductResultAdapterInterface mProductResultsListener=((ProductResultAdapterInterface ) ?????);
Just a quick comment: the mapObject (JsonObject) is created on a onClick method inside a button in ViewHolder, I cannot pass bundle on OnCreate method.
this.btnMarkItemMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
switch (v.getId())
{
case (R.id.markProductinMap):
String mapObj=null;
if (mapObjects !=null)
{
String positionDescription=String.valueOf(position);
String productLatLngValue=txtProductPrice.getText().toString()+";"+ txtItemLanLong.getText().toString();
//tring mapPosition=
mapObj=mapObjects.optString(String.valueOf(position));
if (mapObj!="") //Button not click remove from map
{
btnMarkItemMap.setColorFilter(Color.rgb(0, 0, 0));
btnMarkItemMap.setTag(Color.rgb(0, 0, 0));
mapObjects.remove(positionDescription);
}
else //Button Click add to Map
//
{
btnMarkItemMap.setColorFilter(Color.rgb(255, 51, 102));
btnMarkItemMap.setTag(position);
try {mapObjects.put(positionDescription, productLatLngValue);}catch (JSONException ex){}
if (mapObjects.length()>0)
{
mProductResultsListener.showResultsInMap(mapObjects);
}
}
}else{
mapObjects=new JSONObject();
}
break;
}
}
});
where have you assigned the variable mProductResultsListener?
you need to assign this to the object of the fragment by passing it into the adapter. Otherwise its value is null and you will get a NullPointeException if you call a function on a null object.
If you have, then please update the question with that code.
You can pass the data using bundles like this
SomeFragment someFragment = new SomeFragment();
Bundle bundle = new Bundle();
bundle.putString("value1", "2");
bundle.putString("value2", "23");
bundle.putString("value3", "276");
bundle.putString("value4", "27");
bundle.putBoolean("flag", true);
someFragment.setArguments(bundle);
And in SomeFragment
Bundle bundle = getArguments();
strValue1 = bundle.getString("value1");
strValue2 = bundle.getString("value2");
and so on for getting all the passed data from bundle
ProductResultsListFragment yourFragment = new ProductResultsListFragment();
Bundle bundle = new Bundle();
bundle.putString("yourJsonObject", yourJsonObject.toString);
yourFragment.setArguments(bundle);
public class ProductResultsListFragment...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle savedInfo = this.getArguments();
String savedJsonString = savedInfo.getString("yourJsonObject");
JSONObject myJsonObject = new JSONObject(savedJsonString);
//....
On my Fragment adapter init, I added:
ProductResultAdapterInterface mProInterface=(ProductResultAdapterInterface) this;
mAdapter = new ProductSearchAdapter(R.layout.product_results_cardlist,getActivity(),productListFeed,mProInterface);
on my adapter constructor I changed the signature to accept the Interface as a parameter passed from the Fragment
public ProductSearchAdapter (int rowLayout, Context context,List<Product> feedList,ProductResultAdapterInterface mProductResultsListener) {
this.feedItemLists=feedList;
this.rowLayout = rowLayout;
this.mContext = context;
this.mProductResultsListener=mProductResultsListener;
}
Then I was able to access the method and not getting NPE. thanks all

Transferring multiple strings between Fragments of the same activity with tags

I am having trouble figuring out how to share data between my two fragments which are hosted on the same activity.
The objective:
I want to transfer string from the the selected position of a spinner and an image url string from a selected list view position from fragment A to fragment B.
The Attempt:
I read the fragments doc on this problem here http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
And went ahead an created the following Interface to use betweeen the Fragments and the Host Activity.
public interface OnSelectionListener {
public void OnSelectionListener(String img, String comments );
}
Then I proceeded to implement it in my fragment A's onCreateView method like so:
postList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
ListData link = data.get(position);
String permalink = link.getComments();
String largeImg = link.getImageUrl();
Fragment newFragment = new DetailsView();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
//pass data to host activity
selectionListener.OnSelectionListener(permalink,largeImg);
}
});
And also in the onAttach method
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
selectionListener = (OnSelectionListener)getActivity();
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement onSelectionListener");
}
}
In the Host activity I implemented the interface I wrote and overrided the method like so:
#Override
public void OnSelectionListener(String img, String comments) {
DetailsView detailsView = new DetailsView();
DetailsView dView = (DetailsView)getSupportFragmentManager().findFragmentByTag(detailsView.getCustomTag());
dView.setInformation(img, comments);
}
In Fragment B I set a "tag" the following way
private String tag;
public void setCustomTag(String tag)
{
this.tag = tag;
}
public String getCustomTag()
{
return tag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCustomTag("DETAILS_VIEW");
And my thinking is that that the information can be passed to Fragment B by calling this method from the host activity
void setInformation (String info, String img){
RedditDetailsTask detailsTask = new RedditDetailsTask(null,DetailsView.this);
detailsTask.execute(info);
setDrawable(img);
}
What I need:
I want to know how to properly use tags to get this to work, I dont have any fragment id's declared in my xml and rather opted to exchange fragments in a fragment_container.
I also am not sure if this is a good way to pass multiple strings between fragments. I am a newbie programmer so I know my logic probably looks pretty embarrassing but I am trying to do my best learn to do this right. I would appreciate it if you more senior developers can point me in the right direction for doing this.
You don't need to use tags. Take a look at this example. The Activity implements an interface that allows you to talk from Fragment1 back to the Activity, the Activity then relays the information into Fragment2.
I've left out all the android stuff about FragmentManager etc.
interface FragmentListener {
void onTalk(String s1);
}
public class MyActivity extends Activity implements FragmentListener {
Fragment2 fragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// Find fragment2 and init
}
#Override
public void onTalk(String s1) {
fragment2.onListen(s1);
}
private static class Fragment1 extends Fragment {
private FragmentListener communication;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
communication = (FragmentListener) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_one, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// or in an onClick listener
communication.onTalk("blah blah");
}
}
private static class Fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_two, container, false);
}
public void onListen(String s1) {
Log.d("TADA", s1);
}
}
}
My approach would be, when you get the callback in activity through the OnSelectionListener interface, I would create the Fragment B object and set arguments to it as follows:
#Override
public void OnSelectionListener(String img, String comments) {
DetailsView detailsView = new DetailsView();
Bundle args=new Bundle();
args.putString("img",img);
args.putString("comments",comments);
detailsView.setArguments(args);
//code here to replace the fragment A with fragment B
}
Then in Fragment B's onCreate method you can retrieve the values as follows:
#Override
public void onCreate(Bundle savedInstanceState) {
Bundle args=getArguments();
String img=args.getString("img");
String comments=args.getString("comments");
//do whatever you want to do with the varaibles
}
You could try to make two public static String's in your B fragment.
it Would look like something like this
public static String img;
public static String comment;
The you set the variables before making the transaction to fragment B
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
SecondFragment.img = new String("imgString"); //Making a new string so incase you change the string in bfragment, the values wont change in here
SecondFragment.comment = new String("comment");
// Commit the transaction
transaction.commit();
Then in the onStop(), or onDestroy() - depending on when you want the variables to be null, check this - you set the the static variables to null, so they dont take memory space
public void onDestroy(){
super.onDestroy();
img = null;
comment = null;
}

Categories