In my fragment I have a recycler view and set adapter to it. With adapter's help I can start start second activity by clicking on items in recycler view. But when I finish second activity I need to call one method again in my fragment.
I can start activityForResult only in adapter, but I write onActivityResult method in it.
How can I get result from the activity or call method in fragment again? Is it possible to get result from activity in adapter?
In general, the Adapter should only care about creating RecyclerView cells. Any other logic is better put elsewhere (Activity/Fragment, or better - ViewModel/Presenter)
In case you don't have a view model per RecyclerView cell, I would use an interface to let the Fragment know that an item was clicked:
public interface ItemClickedListener {
fun itemClicked(String itemName)
}
In your Adapter:
public class YourAdapter(private val listener: ItemClickedListener): RecyclerView.Adapter<ViewHolder> {
}
In your Fragment (where you create your Adapter) pass "this" as the ItemClickedListener:
adapter = YourAdapter(this)
Have your Fragment implement ItemClickedListener & onActivityResult:
public class YourFragment: Fragment, ItemClickedListener {
override fun itemClicked(String itemName) {
startActivityForResult(...)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Let your adapter know whatever is needed
}
}
Back in your Adapter, instead of calling startActivityForResult upon item click - call listener.itemClicked
This is a basic example of removing the navigation logic from the Adapter.
Now the Fragment is making decisions about navigation, which might be OK if no business logic is involved.
For cases where more business logic is needed, a better paradigm should be used (MVP, MVVM, MVI, etc..).
As Android recommends using MVVM, I would advice you to read this:
https://developer.android.com/topic/architecture
Related
I am currently recording a message and initialising the objects in one fragment. I'd like to pass it to my main activity. However, I can pass an image between fragments using this:
public void captureImage() {
mCamera.captureImage(new CameraKitEventCallback<CameraKitImage>() {
#Override
public void callback(CameraKitImage cameraKitImage) {
((MainActivity) getActivity()).setBitmapToSend(cameraKitImage.getBitmap());
((MainActivity) getActivity()).openDisplayImageFragment();
}
});
}
I have initialised a media recorder within the class. Is there any way to do this?
If the Main Activity is hosting your fragment, then you can send the data from fragment to its parent Activity by - Interface callbacks or creating a public method in your Activity.
Since you can always get the reference to the parent Activity using getActivity(), you can cast it and pass values to the public method. Eg:
myActivity=(MainActivity) getActivity ();
myActivity.receiveAudio(<"Pass the data as object or in byte[]">);
Sending data from a fragment to another activity require to add Intent extras. Eg:
myIntent.putExtra("myKey",<"Place your object or byte array">);
startActivity(myActivity);
I wonder how to pass data by pressing tab. I have two tab in activity, named Info and Details. When Details tab is clicked, I want to pass the title editText to next activity.
P/S : Without button clicked
MainActivity
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(p0: TabLayout.Tab?) {
}
override fun onTabSelected(p0: TabLayout.Tab?) {
val position = p0?.position
when (position) {
0 ->
supportFragmentManager.beginTransaction().replace(
R.id.frame_container,
CreateWOInfoFragment()
).addToBackStack(null).commit()
else -> supportFragmentManager.beginTransaction().replace(
R.id.frame_container,
CreateWODetailsFragment()
).addToBackStack(null).commit()
}
}
override fun onTabUnselected(p0: TabLayout.Tab?) {
}
})
FragmentOne would be sending the data entered in EditText to FragmentTwo.
So add an interface in fragment one and let the activity implement this interface,
in Fragment one call the method to send data and in main fragment will handle it to send it to fragment two.
Please check this example Android Passing Data between Fragments
I have RecyclerView in cart activity. I want to clear this RecyclerView on pressing checkout activity's complete order button.
Here I tried to describe the scenario:
I can think of two possible solutions:
Start the checkout activity with startActivityForResult() and then return a value which indicates whether or not to clear the RecyclerView. See Getting a Result from an Activity for details.
Store the cart contents in a on disk in a file or database. The data can include a flag which indicates if the purchase has been completed. The cart activity then only loads data for items which are in the cart but not yet paid for.
Just check start activity for result how it work
refrance -https://stackoverflow.com/a/10407371/4741746
Than in onActivityResult method you can update your adapter by using notifyDataSetChanged() or refresh method
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
ArrayList<String> yourNewList= new ArrayList<String> ();
adapter.Refresh(yourNewList);
}
if (resultCode == Activity.RESULT_CANCELED) {
//Write your code if there's no result
}
}
}
public void Refresh(ArrayList<String> datas) { //your bean
this.mStrings.clear(); //mStrings is your bean ArrayList
this.mStrings.addAll(datas);
notifyDataSetChanged();
}
put this Refresh method in your adapter if you want totally refresh adapter
on complete order button click send a local broadcast to the previous recyclerView activity where on receiving the broadcast clear the list and update the recyclerView. Then your recyclerView will be cleared.
As mentioned above it would be best to go with startActivityForResult This will prevent your cart activity from being destroyed when you start checkout activity and cart activity can handle the end result.
Another option would be:
1.create a singleton data class to save all data.
2.declare getter,setter ,allClear and getInstance(static) methods.
3.Get a instance of data class in the cart activity and populate list.
4.Get a instance of data class and call allClear to delete data in Checkout activity.
This approach would keep cart list data independent from different activities. So all you need is call static getInstance method of data class and call allClear no matter which activity you are in.
I am stuck with a problem where I need to update the value of a adapter variable in another activity and coming back to first activity should also get that updated value.
my current flow is like. I am staring the BarDetailsActivity and passing the modal with intent from inside the adapter class like:
Intent barDetailIntent = new Intent(getApplicationContext(), BarDetailActivity.class);
barDetailIntent.putExtra("isfav", barsList.get(position));
barDetailIntent.putParcelableArrayListExtra("barlist",barsList);
mContext.startActivity(barDetailIntent);
Then on another activity I am getting that model from intent and changing its variable values as:
gbar = in.getParcelableExtra("isfav");
blist= in.getParcelableArrayListExtra("barlist");
if (gbar.getmFavourite()) {
gbar.setmFavourite(false);
} else {
gbar.setmFavourite(true);
}
Now on going back to my main Activity Value for "gbar.setmFavourite" is not updated on onresume of the MainActivity.
#Override
protected void onResume() {
super.onResume();
if(mAdapter != null){
mAdapter.notifyDataSetChanged(); // here the adapter value is not updated.
}
}
Please help me on this.
Use Event Bus to handle the problem.
Register your First Activity to listen the Event and override
onEvent method.
Fire the stickyIntent with updated dataset from SecondActivity.
In the onEvent method of the FirstActivity call notifyDataSetChanged
with the updated dataset.
I'm having some trouble, and I have done research on the problem but it did not help me.
I have a Main.java class, which is template made pager view of fragments.
I did not modify it in any way, except for getItem() method which now returns my own fragments.
My fragment A is collecting accelerometer data, saving last 120 records in an ArrayList.
It also has graph plots, with Series objects, which I would like to access from fragment B.
This is what I want to do:
In fragment B user presses a button "record data"
This results in fragment A boolean field "recordingOn" changing to true
Now in fragmentA onSensorChange method, after checking for "recordingOn", if it's true it will pass data to an ArrayList that is a field in fragment B
How do I access these fields?
from fragment call
Fragment frag = getActivity().getFragmentManager()..findFragmentByTag("fragment to find tag");
Greensy answer is a valid option (I upvoted him) but you can also refrain from doing so much DataPassing between fragments and let the Activity be a manager for all that.
For that you can create public methods and interfaces in the fragments and let/force the activity implement the interfaces.
Simple example:
public class Act extends Activity implements OnClickListener{
#Override
OnClick(View v){
if(v.getId()==R.id.btn_recordData){
fragA.startRecording();
}
}
}
then FragA you must create that method:
public class FragA extends Fragment{
private boolean isRecording
public void startRecording(){ isRecording = true; // also init the sensor stuff }
public void stopRecording() { isRecording = false; // also stop the sensor stuff }
}
then on FragB you can:
public class FragB extends Fragment{
onCreateView(...){
// initialise all the views and find the button, let's call it Button btn;
btn.setOnClickListener((OnClickListener)getActivity());
}
}
does that make sense?
A way to do that is to use your own Application class and store your ArrayList in there
You can then access it in any point of your application, if you got a Context :
ArrayList<AccelerometerData> myAccelerometerData = ((MyApplication) mContext.getApplicationContext()).getAccelerometerData();
Be carefull about this solution since your ArrayList will be alive during all the application run