I am using a Fragment class.
I add it using
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Search fragment = new Search(maincontrolActivity.this);
fragmentTransaction.add(R.id.mainLayout,fragment , "MY_FRAG");
fragmentTransaction.commit();
this.FragmentObject = fragment
when I do refresh the control,I recall this code but by passing this.FragmentObject but I think it be garbage collected because the = refere to the same object , and when say add, it free the old fragement which is the same
so do I need a deep copy or any way to refresh ?
any idea
Ok. So what I would do is have an Interface defined and have each Fragment register with the Activity for a callback when the refresh button is clicked. Then in the fragment itself have it refresh its data. If that means getting new data, switch to a ProgressBar, get the data from the server, and repopulate the Views. Here is an entire article on creating Interfaces in Activities and calling Fragments from them.
Here is roughly what your code will look like...
The Activity:
public class RefreshActivity extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
findViewById(R.id.refresh_button).setOnClickListener(this);
}
public interface OnRefreshPressedListener {
public void onRefreshPressed();
}
#Override
public void onClick(View v) {
((OnRefreshPressedListener)this.FragmentObject).onRefreshPressed();
}
}
The Fragment:
public class Search extends Fragment implements OnRefreshPressedListener {
#Override
public void onRefreshPressed() {
//TODO: Refresh your data!
}
}
Related
I'm a newbie in android developer. I have a question about transfer with 3 fragments.
I have 3 fragments (A - B - C). I want o transfer data from A -> B -> C.
In each the fragment, data was been changed.
When user click BACK BUTTON, user want to return A with the updated data.
How to return fragment A with the update data?
Thanks.
Here is a sample idea how to achieve communication.
// activity classs
public class SampleActivity extends Activity implements OnFragmentChangeListener {
OnBackPressListener dataFragment;
public void onCreate(bundle){
android.app.FragmentManager fragmentManager=getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
dataFragment = new DataFragment();
fragmentTransaction.add(R.id.audio_permission_button,dataFragment);
fragmentTransaction.commit()
}
#override
public void OnFragmentChange(Bundle bundle){
//here you go.
// write code to load new fragment with same idea. now you have bundle do what you want.
}
#Override
public void onBackPressed() {
// you can call this method from any click event, This just an sample idea.
dataFragment.OnActivityBackPress();
}
}
// interface to communicate with fragment
public interface OnFragmentChangeListener {
public void OnFragmentChange()
}
// fragment class
public class DataFragment extends Fragment implements OnBackPressListener {
OnFragmentChangeListener onFragmentChangeListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onFragmentChangeListener=(OnFragmentChangeListener) getActivity();
}
#Override
public void OnActivityBackPress() {
// pass you data to activity for loading new fragment or to refresh data.
Bundle bundle= new Bundle();
onFragmentChangeListener.OnFragmentChange(bundle);
}
}
// interface behave like mediator
public interface OnBackPressListener {
public void OnActivtiyBackPress();
}
Use interface to achieve this. Implements interface in fragment and activity, as it's a good way to communicate between fragment through activity. Then send the data through interface and extract the data from it.
You can use Interface class to communicate between fragment but it must make sure all the fragment is alive.
You can use SharedPreferences where you can save the data and retrieve it anywhere you like
Can someone please tell me if I'm solving this correctly or if I should go another route?
This is a simplified example: I have 1 Activity and 2 Fragments. Each Fragment has a button that when clicked, relays the click back to the Activity and a Toast pops up within the Activity.
I know that a Fragment communicates with an Activity through an interface. But what If I have multiple Fragments that have a similar Interface. For example, here both Fragments use an onClick type of interface to communicate back to the Activity
static interface OnClickedListener{
public void buttonClicked(View v);
}
Is it better to
A) Create a separate Interface class and attach it within both Fragments. For example Fragment 1:
public class Fragment1 extends Fragment implements OnClickedListener{
private OnClickedListener clickedInterface;
public Fragment1() {
// Required empty public constructor
}
#Override
public void buttonClicked(View v) {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.clickedInterface = (OnClickedListener)activity;
}}
Fragment 2:
public class Fragment2 extends Fragment implements OnClickedListener{
private OnClickedListener clickedInterface;
public Fragment2() {
// Required empty public constructor
}
#Override
public void buttonClicked(View v) {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.clickedInterface = (OnClickedListener)activity;
}
OR
B) Create individual Interfaces unique to the specific Fragment and implement those in the MainActivity instead of the one Interface like mentioned above. Thank you.
First Create your custom fragment which is in implement interface.
public class CustomFragment extends Fragment implements OnClickedListener{
public OnClickedListener clickedInterface;
#Override
public void buttonClicked(View v) {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.clickedInterface = (OnClickedListener)activity;
}
}
Now, you can add in every fragment
(i) Fragment 1
public class Fragment1 extends CustomFragment {
......
}
(ii) Fragment 2
public class Fragment2 extends CustomFragment {
......
}
I wouldn't let the details of any Views contained in a Fragment leak out into the Activity.
Better interfaces would be based on the semantic action involved with the button press, for example createThing() or deleteThing().
The Activity shouldn't really care which View was clicked to initiate the action just that the action needs to happen. When happens to your interfaces if you move the button to the menu, or somewhere else not associated with a View.
If you create interfaces like this, the question of creating copies for different Fragments disappears.
There is a code principal called SOLID. "I" states for https://en.wikipedia.org/wiki/Interface_segregation_principle. It is a good practice to
You should not make universal interface or large ones, you need to create interface that can be "readable" and "understandable" for everyone by interface name and its method names like "articleSelected" or "loginProcessing(String loginName)" etc
I have 2 fragments which are instantiated from the same class as the layouts are identical like so:
getSupportFragmentManager().beginTransaction().
add(R.id.leftContainer,new LeftFragmentClass(),"leftFrag").commit();
getSupportFragmentManager().beginTransaction().
add(R.id.rightFrag,new LeftFragmentClass(),"rightFrag").commit();
Within LeftFragmentClass there is a callback method which is called when the button within the fragment is pressed. After this some processing is done and data is displayed, however, right now the callback cannot distinguish which button was pressed. Is there a function which can return which fragment button was pressed?
For this type of condition i create a function inside fragment which will return me the instance of fragment and make the fragment constructor private something like:-
public class LeftFragmentClass extends Fragment{
private String fragmentTag = null;
public LeftFragmentClass(){}
public static LeftFragmentClass newInstance(String tag){
LeftFragmentClass mLeftFragmentClass = new LeftFragmentClass();
Bundle bundle = new Bundle();
bundle.putString ("tag",tag);
mLeftFragmentClass.setArgument(bundle);
return mLeftFragmentClass;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
tag = getArguments().getString("tag")
}
}
So i used newInstance function to create instance of LeftFragmentClass and pass the tag to it which i m setting to Fragment argument using bundle and inside onCreate get bundle using getArguments and from it the tag value. Pass this tag value as one of the parameter to your callback method to identify which button was clicked.
So from activity for getting instance of LeftFragmentClass you can write as
LeftFragmentClass mLeftFragmentClassLeft = LeftFragmentClass.newInstance("left")
LeftFragmentClass mLeftFragmentClassRight = LeftFragmentClass.newInstance("Right")
==== Edit ====
keep the fragment class constructors always public don't make it private as i suggested above in my sample code. Making it private will cause application to crash with exception
java.lang.RuntimeException: Unable to start activity
ComponentInfo{MainActivity}:
android.support.v4.app.Fragment$InstantiationException: Unable to
instantiate fragment com.thatswhy.AppAlertDialog: make sure class name
exists, is public, and has an empty constructor that is public
Fragment fragment = getFragmentManager().findFragmentByTag("Tag")
As per provided the info you can do something like this, in your callback method pass the button object and check accordingly,
Some code snippet to explain the same :
Suppose your callback method is onButtonClick() then you can pass button object like :
public void onButtonClick(Button button){
// check here with button id
if(button.getId() == R.id.button1) {
} else if(button.getId() == R.id.button1) {
}
}
Hope this makes things clear..
The cleanest way of doing this I've seen is to create two distinct View.OnClickListener(s) in the Activity.
Have a getter() for each. public View.OnClickListener getLeftButtonPressed(), public View.OnClickListener getRightButtonPressed()
Then when you instantiate your left and right instances of your fragment, just pass in the appropriate 'View.OnClickListener' to the constructor of the Fragment. This not only reduces the code in the Fragment(s), it also centralizes the 'logic' of what to do when buttons are pressed.
public class MyActivity extends Activity {
// create the two listeners
View.OnClickListener leftButtonListener = new View.OnClickListener() {
public void onClick(View v) {
leftButtonClicked(v);
}
});
View.OnClickListener rightButtonListener = new View.OnClickListener() {
public void onClick(View v) {
rightButtonClicked(v);
}
});
// 2 getters
public View.OnClickListener getLeftListener() { return this.leftButtonListener; }
public View.OnClickListener getRightListener() { return this.rightButtonListener; }
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.content_layout_id);
}
// actual logic of what to do when each button is pressed.
private void leftButtonClicked(View v){
// some logic here
}
private void rightButtonClicked(View v){
// some logic here
}
}
This removes you later having to keep track of which button was pressed by making use of strings and if/then/else blocks, etc.
Add a parameter to interface callback function in your fragment;
interface Interfacecallback{
public void callbackfunction(int fragid);
}
Interfacecallback interfacecallback;
//in your button click
//pass 1 for fragment right
//pass 2 for fragment left
interfacecallback.callbackfunction(1);
You can check the fragment tag using this line of code if it exists:-
Fragment mapFragment = getFragmentManager().findFragmentByTag("MapRestaurantFragment");
So i have a FragmentPagerAdapater called SectionsPagerAdapter and a fragment called TeamFragment where I display data from a specific team. So basically I don't want to create different fragments for each team. That is an overkill. I just want 1 fragment which basically connects to the backend then collects the data based on the team then displays that data. But I dont know how to pass the Team name(a string type) from SectionsPagerAdapter to the TeamFragment so that in TeamFragment, I can easily know what to retrieve from the backend. My backend in parse.com. Please help me figure this out and learn. Thanks
So this is was solved my problem. In my sectionsPagerAdapter class i had the below code
Bundle args = new Bundle();
args.putString("TeamName", team);
TeamFragment teamFragment = new TeamFragment();
teamFragment.setArguments(args);
In onCreateView of my TeamFragment, i had the following
Bundle bundle = this.getArguments();
mTeam = bundle.getString("TeamName");
hope this can help someone else. Thanks
Communicating data into fragments is typically done through a simple setter function that is called by the activity that instantiates or contains the fragment:
public class MyActivity extends FragmentActivity {
#Override
protected void onCreate(Bundled savedInstanceState) {
// ...
TeamFragment fragment =
(TeamFragment) (getSupportFragmentManager().findFragmentById(fragmentId));
fragment.setTeamName(teamName);
// ...
}
For communicating data back to the activity, is typically done using a fragment-specific "Listener" interface. This listener can be attached using the same method (by calling a method on the fragment in the parent activity to register the listener) or it can be done by requiring that the parent Activity implement the listener interface, and casting the parent activity to this listener interface in onAttach() (though the latter approach is not as clean of an approach). Example:
public class MyActivity extends FragmentActivity {
#Override
protected void onCreate(Bundled savedInstanceState) {
// ...
TeamFragment fragment =
(TeamFragment) (getSupportFragmentManager().findFragmentById(fragmentId));
fragment.setTeamName(teamName);
fragment.setTeamSelectedListener(new TeamSelectedListenerImpl());
// ...
}
Or:
public class TeamFragment extends Fragment {
public interface TeamSelectedListener {
// ...
}
// ...
#Override
protected void onAttach(Activity activity) {
teamSelectedListener = (TeamSelectedListener) activity;
}
// ...
}
public class MyActivity
extends FragmentActivity
implements TeamFragment.TeamSelectedListener {
// ...
}
Please please don't minus my question i confused when googling.
I used Android Tab Layout with Swipeable Views in my code for when user pressed setting button on an activity.
now I need send message from TopRatedFragment.java that extends from fragment to the activity that call the mainActivity of "Android Tab Layout with Swipeable Views".
You can do this by implementing a call back
create an interface first
public interface CommunicationInterface {
public void onSuccess();
public void onFailed();
}
then in your activity implement the interface
public class YourActivity extends ActionBarActivity implements CommunicationInterface {
//default functions
#Override
public void onSuccess() {
//stuff you want to do in the acivity
}
#Override
public void onFailed() {
//stuff you want to do in the acivity
}
}
Now in the fragment
public class yourfragment extends Fragment {
CommunicationInterface callback;
//stuffs that usually come in yor fragment and like OncreateView etc
#Override
public void onActivityCreated(#Nullable Bundle outState) {
super.onActivityCreated(outState);
//after all the stuff you want to do in your fragment then implement //call back function to communicate with the activity
callback= (CommunicationInterface) getActivity();
callback.onSuccess();//according to your purpose use where ever you like
callback.onFailed();//according to your purpose use where ever you like
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback= (CommunicationInterface) activity;
}
}
Take a close look on this reference:
Creating event callbacks to the activity
The android docs recommend using this pattern of having the parent activity implement an interface of the fragment (Basically calling methods on it)
class MyFragment extends Fragment {
interface Listener {
public void onSomeEvent();
}
private void somethingHappeninInTheFragment() {
// let the activity know
((Listener) getActivity()).onSomeEVent();
}
}
class MyActivity extends Activity implements MyFragment.Listener {
// etc
#Override
public void onSomeEvent() {
// handle the message from the fragment
}
}
Explained with a more concrete example here: http://developer.android.com/guide/components/fragments.html#EventCallbacks
Here's the solution:
Step 1 : From your fragment.
Intent i = new Intent(getActivity(), YourActivity.class);
i.putExtra("key", "Your value1");
i.putExtra("key2", "Your value2");
i.putExtra("key3", "Your value3");
getActivity().startActivity(i);
Step 2 : In your Activity where you want the result
Intent getResults = getIntent();
String firstValue = getResults.getStringExtra("key1");
String secondValue = getResults.getStringExtra("key2");
String thirdValue = getResults.getStringExtra("key3");
Use those values your needs are.
Hope this helps.. :)