How to update a Fragment that has a Gridview populated from Sqlite - android

I have a ViewPager with two tabs which holds fragment. Inside the first fragment, I have a Gridview which is being populated with Sqlite Db.
I have an custom alertdialog in my Activity, which is the parent of the Fragments.
When the alertdialog closes, it either adds/removes/updates the Sqlite Db:
DataBaseHelper dbh = DataBaseHelper(this);
...
positiveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dbh.addVal(new TheData(editName.getText().toString(), editAge.getText().toString())); //adds a row to the Sqlite Db
dialog.dismiss();
//on dismiss, refresh the Fragment, which in turn will display the updated GridView.
}
});
...
How can I update complete the following:
//on dismiss, refresh the Fragment, which in turn will display the updated GridView.

You could use Intents and Intent Filters with a Broadcast Receiver
for this.
Create a BroadcastReceiver instance in the fragment where you want to update the data.
Create an IntentFilter and set an action string (maybe 'db.update') to it and register it with your application context (you could do this via your fragment by calling getActivity().getApplicationContext().registerReceiver(receiver, filter).
In your AlertDialog, after you update your database, create an Intent with the same action string you set above (in our case, 'db.update') and use context to send it out (getActivity().getApplicationContext().sendBroadcast(intent)). Your BroadcastReceiver's onReceive() method would be called in your fragment and you can call the method to refresh or reload your data there. See sample code below:
Say this is your fragment
public class YourFragment extends Fragment {
private GridView mGridView;
private BaseAdapter mAdapter;
private BroadcastReceiver mReceiver;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflate view as usual
View view = inflater.inflate(R.layout.yourlayour, container, false);
...
//create instance of broadcast receiver
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) { //when intent is receiver, this method is called
if(intent.getAction().contentEquals("db.update")){
//update intent received, call method to refresh your content loader
refreshFragment();
}
}
};
//create a new intent filter
IntentFilter mDataUpdateFilter = new IntentFilter("db.update");
//register our broadcast receiver and intent filter
getActivity().getApplicationContext().registerReceiver(mReceiver, mDataUpdateFilter);
return view;
}
#Override
public void onDestroy() {
super.onDestroy();
//never forget to unregister the receiver when you're done, it could cause your app to crash
//if it receives an intent and calls null pointing methods in your code
getActivity().getApplicationContext().unregisterReceiver(mReceiver);
} }
Then in your AlertDialog as you did above, send the intent to this receiver by:
DataBaseHelper dbh = DataBaseHelper(this);
...
positiveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dbh.addVal(new TheData(editName.getText().toString(), editAge.getText().toString())); //adds a row to the Sqlite Db
//Create an intent with our action
Intent updateIntent = new Intent("db.update");
//send the intent by
getContext().getApplicationContext().sendBroadcast(updateIntent);
dialog.dismiss();
}
});
...
Don't forget to unregister your broadcast receiver when your fragment is destroyed. Call getActivity().getApplicationContext().unregisterReceiver(receiver); in your onDestroy() method.
I should also point out that the onReceive() method of your broadcast receiver would always be called on the main thread, even if you send your intent from a background thread.

Here is a trick that i use to access Fragments inside a ViewPager
in my custom viewPagerAdapter, i add two methods
public class CustomViewPagerAdapter extends FragmentPagerAdapter {
.....
private String getFragmentTag(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
//mFragManager is a reference to FragmentManager
public Fragment getFragmentByTag(int containerId, int position) {
return mFragManager.findFragmentByTag(getFragmentTag(containerId, position));
}
}
then in your activity or wherever you can access the customViewPager
YourFragment frag = (YourFragment) customViewPager
.getFragmentByTag(YouViewPager.getId(), position);
after that, add a method in YourFragment refreshData (if you like the name!) and in it refresh the grid
Hope this help

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frag).attach(frag).commit(); //frag is my Fragment instance...
Each time the dialog closed and it did the trick... simple and easy!

Related

Hello! I need some help in updating LIstView in Fragments

How can I update ListView in the other Fragment?
public class ChooseCS extends FragmentActivity {
final private Context context = this;
private HashMap<String, List<String>> mCitiesStreets = null;
private View rootViewStreetChangeFragment = null;
private SimpleAdapter adapter;
...
private static final int NUM_PAGES = 3;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
...
and two Fragments
public class CityChangeFragment extends Fragment {
and
public class StreetChangeFragment extends Fragment {
...
mMapDataAdapter.put("streets", fillcities);
adapter = new SimpleAdapter(
rootViewStreetChangeFragment.getContext(),
mMapDataAdapter.get("streets"), R.layout.grid_streets_4_7,
from, to);
mDataListViewStreets.setAdapter(adapter);
...
I need make update ListView in StreetChangeFragment from CityChangeFragment where I doing changing data
You can use LocalBroadcastManager to achieve this.
In your StreetChangeFragment write below code
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Register to receive messages.
// We are registering an observer (mMessageReceiver) to receive Intents
// with actions named "custom-event-name".
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
And use below method to send broadcast message from CityChangeFragment to StreetChangeFragment
private void sendMessage() {
Log.d("sender", "Broadcasting message");
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Note: You can pass data using intent (here you can position also on which you want to update data in listview)
You can check below link to learn more about LocalBroadcastManager
https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
Interface is good idea,The idea is basically to define an interface and let the activity implement that interface.
Once it has implemented that interface, you could do anything you want in the method it overrides.
There is a good tutorial on Simple Developer Blog how to do exactly this kind of thing.
And you need t declare a method in fragment and it can be executed from the activity by getting the fragment instance from adapter like
Fragment fragment= mPagerAdapter.getItem(int positon);
((StreetChangeFragment )).updateList();
in StreetChangeFragment declare method and do what else you want, Thank you

Call fragment from another fragment after some delay

I searched all over the web, couldn't find a good reference on how to call fragment from another fragment.
Fragment A -> Fragment B (fragment A calls fragment B after 3 seconds)
Well, first of all you need to consider that it's a very bad idea to keep somehow a direct reference from FragmentA to FragmentB. Why:
FragmentB may be recreated and you may keep a reference to an older reference of FragmentB. So you have a memory leak.
FragmentB may be not created, added or visible. So you would have a null/unusable reference.
For this reason you need to consider methods that base on sending messages from FragmentA to FragmentB. I see several options:
Send a broadcast message using a custom action from FragmentA. FragmentB registers itself as a receiver for this kind of message (in onCreate/onResume/onAttach and de-register in onDestroy/onPause/onDetach) and when the message arrives it can handle it. This is very suitable if you have no data to send from FragmentA to FragmentB or if you do these are primitive types or easy-to-implement Parcelables. Here's an example:
Have this in FragmentA:
private void sendMessageToFragmentB(String someData) {
Intent messageIntent = new Intent("com.your_package.A_TO_B_ACTION");
messageIntent.putExtra("DATA_VALUE", someData);
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(messageIntent);
}
While in FragmentB you could have this:
public class FragmentB extends Fragment {
private BroadcastReceiver messagesFromAReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ("com.your_package.A_TO_B_ACTION".equals(intent.getAction())) {
String dataFromA = intent.getStringExtra("DATA_VALUE");
dataFromAReceived(dataFromA);
}
}
};
protected void dataFromAReceived(String data) {
// here you have the data
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
IntentFilter messageFromAIntentFilter = new IntentFilter("com.your_package.A_TO_B_ACTION");
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(messagesFromAReceiver,
messageFromAIntentFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(messagesFromAReceiver);
}
}
Use the hosting activity as a proxy: The host activity implements some kind of interface defined in FragmentA and when requested it can search if it can find FragmentB and if so call some method in there. The advantage is that you can send any data, no matter its weight. The base idea is descrived in Android dev articles. To exemplify, you could have FragmentA as:
public class FragmentA extends Fragment {
public static interface CallerProxy {
public void sendCustomMessage(Object... dataParams);
}
private CallerProxy proxyActivity;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof CallerProxy) {
this.proxyActivity = (CallerProxy) activity;
}
}
#Override
public void onDetach() {
super.onDetach();
this.proxyActivity = null;
}
private void sendMessageToFragmentB(String someData) {
if (proxyActivity != null) {
// send whatever data
proxyActivity.sendCustomMessage(new Integer(1), new Object());
// or don't send anything ...
proxyActivity.sendCustomMessage();
}
}
}
The proxy activity would have at least these methods and signature:
public class MyProxyActivity extends FragmentActivity implements CallerProxy {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// call setContentView and then make sure you've added FragmentA and
// FragmentB.
}
#Override
public void sendCustomMessage(Object... dataParams) {
// FragmentB must be identified somehow, either by tag,
// either by id. Suppose you'll identify by tag. This means you've added
// it previously with this tag
Fragment fragment = getSupportFragmentManager().findFragmentByTag("FragmentB-TAG");
if (fragment != null) {
FragmentB fragB = (FragmentB) fragment;
fragB.dataFromAReceived(dataParams);
}
}
}
While in FragmentB all you need is a method that can be called with above sent parameters:
public void dataFromAReceived(Object ... data) {
// here you have the data
}
Use or implement some sort of event bus. Some general details here. For Android I remember that Otto event bus was very handy and easy to use. Here's a link with this. This is very similar to first option as you need anyway to register and un-register.
In the end it depends on what you need to send as a message, when should it be received and how flexible does it need to be. ... your choice!
Enjoy programming!
Fragments are not supposed to connect to each other directly, that may be your problem in finding a decent guide to do this.
Your approach makes the assumption that a fragment B will always be reachable (and ready) for a fragment A to interact, and that is actually not true, will kill the flexibility of your Fragment and will cause you problems in the future.
A better approach to interaction of Fragments is to talk only through interfaces that talk directly to a activity that can handle who is alive when where and should receive what.
-> http://developer.android.com/training/basics/fragments/index.html
This Android guide above, specifically on the last topic, shows you how to do this.
i hope this code help you..
in your first fragment add this code
onCreateView
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity());
IntentFilter intentFilter = new IntentFilter("update");
// Here you can add additional actions which then would be received by the BroadcastReceiver
broadcastManager.registerReceiver(receiver, intentFilter);
#Override
public void onDestroyView() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
super.onDestroyView();
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals("update")) {
// perform your update
getOngoingOrderData();
}
}
};
in your second fragment add this code where you send broadcast..
Intent intent = new Intent("update");
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity());
broadcastManager.sendBroadcast(intent);

How to pass result from second fragment to first fragment

In my app I have two fragments say fragmentA and FragmentB. When I click on a button in fragmetA, a list is opened in fragmentB. Now when I select an item from list in fragmentB I want the result to be passed to fragmentA. I am using only one TabActivity for all fragments. When list item is selected in fragmentB I am popping out fragmentB from stack so that I can directly go back to fragmentA.
Does anyone knows how to pass result to previous fragment.
Thanks.
Update
Activity is the parent controller and should take responsibility for handling those events raised by its fragments/views, which concern something outside of the scope of fragment/view itself.
A Fragment is to act as a sub-controller of Views it hosts. All the events and communication between its own views, the fragment should handle itself. When there is an event outside of a fragment's scope and responsibilities (like sending data to another fragment), that event should be escalated to its parent controller, the Activity.
Old
From this tutorial : http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
Its better to let the activity apply changes to its fragment than passing values directly between fragments. Let your Activity implement a FragmentListener interface with onQuery(Bundle data) and onResult(Bundle data) methods.
Create a FragmentListener varaible in each of your fragments and then override onAttach() of each fragment as:
public void onAttach(Activity activity) {
super.onAttach(activity);
//---register parent activity for events---
try{
fragmentListener = (FragmentListener) activity;
}catch (ClassCastException e)
{
throw new ClassCastException("Parent activity must implement interface FragmentListener.");
}
}
This will enforce your child fragments to be automatically registered to parent Activity.
Also, remember to release fragmentListener reference in onDetach().
Now you can call your Activity from fragments.
On the other side, your Activity can always search for a fragment using getFragmentManager().findFragmentByTag("fragmentA") or findFragmentById("FragmentA").
If it can find your Fragment, Then it can cast it into your FragmentA class and call its methods. Same can be done with FragmentB or any other fragment..
One of the possible solutions:
public class DetachableResultReceiver extends ResultReceiver {
private Receiver mReceiver;
public DetachableResultReceiver(Handler handler) {
super(handler);
}
public void clearReceiver() {
mReceiver = null;
}
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
public interface Receiver {
public void onReceiveResult(int resultCode, Bundle resultData);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (mReceiver != null) {
mReceiver.onReceiveResult(resultCode, resultData);
}
}
}
First fragment implements DetachableResultReceiver.Receiver and creates DetachableResultReceiver object:
mReceiver = new DetachableResultReceiver(new Handler());
mReceiver.setReceiver(this);
Then you can pass it to second fragment arguments:
Bundle bundle = new Bundle();
bundle.putParcelable(Consts.EXTRA_RECEIVER, receiver);
fragment.setArguments(bundle);
And use it in second fragment:
receiver = getArguments().getParcelable(Consts.EXTRA_RECEIVER);
receiver.send(Consts.SOME_MESSAGE, someData);
In fragmentB.java set an OnClickListener to perform a method in the main class. Pass an arguement in fragmentB.java to the main class that is the variable, and handle the rest of it in your main class. Though fragments shouldn't really be dependent on activities at all. Fragments were made to plug and play anywhere.
This Example Shows EditTextListener:
myAwesomeActivity.java
fragmentA.java
fragmentB.java
fragmentB.java:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
int x = 3;
EditText ed1 = (EditText) getView().findViewById(R.id.editText1);
ed1.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction()) {
((myAwesomeActivity) getActivity()).myMethod(x);
}
return false;
}
});
}
myAwesomeActivity.java:
publiv void myMethod (int x){
//Do whatever you want with variable
}
All you have to do is implement the correct type of listener, but the main point is shown. In one fragment activity, call a method and pass a variable to the main activity. From the main activity you can send it to your other fragment activity if you'd like.
You can also use SharedPreferences to save some string and after return back to the first fragment load it and clear.

Update fragment on dialog fragment option selection

I have fragment that on a component click pop-ups DialogFragment. This dialog fragment holds list of options. When an option from list is selected I want to notify fragment so I can run fields update procedure.
I did something like this
#Override
public void onClick(DialogInterface dialog, int item) {
updateSharedPreference(item);
Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick");
OnCloseListDialogListener act = (OnCloseListDialogListener) getActivity();
act.onDialogListSelection();
dismiss();
}
However this getActivity() calls on FragmentActivity and not the fragment that triggered the dialog fragment.
I could kill currently open/running fragment and call a new instance that would get updated fields, but that is dirty solution that I would prefer to avoid.
Any suggestions how to go about this update of fragment once option selected in dialog fragment?.
Just coming back with solution. My problem was actually forwarding current fragment getTag() string as parameter of show() for DialogFragment. If anyone interested here is working sample.
Create simple listener
public interface OnCloseListDialogListener {
public void onDialogListSelection();
}
Create new dialog that will extend DialogFragment
public class ListDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
private PersonaData[] mPersonaData;
private String[] mPersonaName;
private final String TAG;
public static ListDialogFragment newInstance(PersonaData[] personaData, String tag) {
ListDialogFragment dialog = new ListDialogFragment(personaData, tag);
Bundle bundle = new Bundle();
dialog.setArguments(bundle);
return dialog;
}
private ListDialogFragment(PersonaData[] personaData, String tag) {
this.mPersonaData = personaData.clone();
this.TAG = tag;
}
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setCancelable(true);
int style = DialogFragment.STYLE_NORMAL, theme = 0;
setStyle(style, theme);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.dialog_title);
mPersonaName = getData();//Your own implementation here
builder.setNegativeButton("Cancel", this);
builder.setSingleChoiceItems(mPersonaName, -1, new SingleChoiceListener());
return builder.create();
}
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
private class SingleChoiceListener implements DialogInterface.OnClickListener {
#Override
public void onClick(DialogInterface dialog, int item) {
updateSharedPreference(item);
OnCloseListDialogListener act = (OnCloseListDialogListener) getFragmentManager().findFragmentByTag(TAG);
act.onDialogListSelection();
dismiss();
}
}
}
And then in fragment from which you wish to call this dialog do as bellow. DIALOG is just String constant I put there just dialog
SOME_CLICKABLE.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
ListDialogFragment dialog = ListDialogFragment.newInstance(mPersona, getTag());
dialog.show(manager, DIALOG);
}
});
It is necessary in most cases that a Fragment be aware that it is running under the context of an Activity of some description and acceptable for the child Fragment to invoke a method on an interface implicitly implemented by the parent Activity (as demonstrated by the cast in your code snippet). When you get your references working as Tomasz points out you'll be golden.
However, :) to aid the re-usability of the dialog fragment I would suggest that you leverage BroadcastReceivers. A BroadcastReceiver simply broadcasts a message saying I did 'x'. The parent activity or in indeed any other top level component can then declare I am listening for 'x'. Once, the event has been fired in the dialog component, this event will be collected by the parent Activity's onReceive where you can run the necessary code to update your fields.
On a personal level, I prefer this loose coupling over the casting interface approach since it forces me to think about the purpose of each Fragment and keep it modular.
If you want to give it a shot then have a read over the dev guide section on BroadcastReceivers and follow the follow steps;
Implement the BroadcastReceiver in your parent activity. Notice an onReceive method is required to be implemented.
Override the parent Activity's onResume method and register the the activity as a receiver of an event with intent action "blah". Something like;
#Override
protected void onResume() {
super.onResume();
registerReceiver(this, new IntentFilter("blah"));
}
Override the parent Activity's onPause method an unregister the activity as the receiver so as to avoid 'leaked receivers' (you'll find out).
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(deleteSpotReceiver);
}
In your DialogFragment onClick fire the event which your parent activity is 'listening' for.
#Override
public void onClick(DialogInterface dialog, int item) {
updateSharedPreference(item);
Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick");
final Intent intent = new Intent();
intent.setAction("blah");
getActivity().sendBroadcast(intent);
dismiss();
}
The parent activity will collect the message and you can continue processing. Let me know if you decide to adopt that method.
Just the way you did it above and add sth like that in your activity :
public void onDialogListSelection() {
AnotherFragment anotherFragment = (AnotherFragment) getSupportFragmentManager()
.findFragmentById(R.id.anotherFragment);
anotherFragment.customMethodToNotifyListHasBeenSelected();
}
Of course, if you are not use Support Library then call getFragmentManager instead of getSupportFragmentManager.

ViewPager Activity to notify a Fragment of a specific event

I have a ViewPager and it is using a FragmentAdapter in order to display several fragments of the same kind. Although these Fragments are basically instantiated from the same class, they are using a ListView to display different information. (Obviously the ListView is being poulated by an ArrayAdapter.)
A background service is also running and is constantly receiving data from the Internet. I want to be able to update a specific Fragment in the ViewPager when my background service has notified me of a specific event.
How can I do that?
A code snippet would be hugely appreciated!
(By the way, I have saw this similar question but I have no idea how to use their suggestion!)
To make it all more simple:
My activity with the ViewPager:
[Fragment 0] [Fragment 1] [Fragment 2]
The background service tells me (via a broadcast) to update the ListView in Fragment 1.
EDIT:
Here are sample codes:
public class ChatWindowPager extends FragmentActivity
{
private ViewPager mViewPager = null;
private ChatFragmentAdapter mAdapter = null;
#Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_window_pager);
this.mViewPager = (ViewPager) findViewById(R.id.chatPager);
this.mAdapter = new ChatFragmentAdapter(getSupportFragmentManager());
this.mViewPager.setAdapter(this.mAdapter);
.
.
.
}
class ChatFragmentAdapter extends FragmentPagerAdapter implements ViewProvider
{
public ChatFragmentAdapter(final FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(final int arg0)
{
String friendId = ..... // Some initializations
ChatWindowFragment f = ChatWindowFragment.newInstance(friendId);
return f;
}
#Override
public int getCount()
{
...
}
#Override
public View getView(final int position)
{
View v = getLayoutInflater().inflate(R.layout.tab_holder, null);
.
.
.
return v;
}
}
}
Now the fragments is defined like this:
public class ChatWindowFragment extends Fragment
{
public String friendId;
private ListView lv;
public static ChatWindowFragment newInstance(final String friendId)
{
ChatWindowFragment chatWindowFragment = new ChatWindowFragment();
Bundle bundle = new Bundle();
bundle.putString("friendId", friendId);
chatWindowFragment.setArguments(bundle);
return chatWindowFragment;
}
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.friendId = getArguments().getString("friendId");
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.chat_window, container, false);
this.friendId = getArguments().getString("friendId");
.
.
.
return v;
}
//The rest of the class
}
As I am using a FragmentPagerAdapter I don't see how I can set the tag of each fragment!
(Obviously, I am not using transactions to add the Fragments!)
EDIT 2:
I would like to know whether what I'm doing, is the correct way to handle what I want to do... Any other solution is also welcome!
Try this,
Register a broadcast receiver in all your fragments... like this
create a class which extends a broadcast receiver in all the classes, for eg:
public class FragmentReceiver1 extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
and register this receiver in you fragment's onCreate ...
for eg. getActivity().registerReceiver(new FragmentReceiver1(), new IntentFilter("fragmentupdater"));
Now assign a unique id to each of you fragment like 1 for Fragment1, 2 for Fragment2 and likewise
now whenever you want to pass any data and update any of the fragment just send a broadcast with the data in intent and "fragmentupdater" as the intent-filter...
For eg:
Intent data = new Intent("fragmentupdater");
data.putString("key","data");
data.putInt("fragmentno",1); // Pass the unique id of fragment we talked abt earlier
activity.sendBroadcast(data);
Now each of your fragment will receive the data but you can verify if the data if for the same fragment by the unique id we passed in it in the onReceive function..., the intent which you get, is the intent we passed above
Have you tried FragmentManager.findFragmentByTag()
FragmentManager manager = getSupportedFragmentManager();
//with support package, else
//FragmentManager manager = getFragmentManager()
Fragment fragment = manager.findFragmentByTag("Tag You Created the Fragment");
if (fragment instanceof Fragment1){
Fragment1 fr = (Fragment1)fragment
fr.updateData(DATA)
//or any method of your choice
}
EDIT: I read carefully! The instanceOf will cast a Fragment into your Fragment class. It was you, who suggested Fragment1 as a name for simpicity. Also, you didn't provide any source to help us. It is true, that you cannot set a Fragment's tag, but why do you think you are able to get its tag?
Usually a Fragment is added through FragmentManagers like
FragmentManager manager = getSupportedFragmnentManager()
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(int containerViewId, Fragment fragment, String tag);
// or transaction.add(Fragment fragment, String tag)
// ...other transactions
transaction.commit()
EDIT2: it's very easy though. according to your code you could just call
Fragment fragment = mAdapter.getItem(0) // 0||1||2
You should consider reading the docs (i.e about FragmenPagerAdapter) and post your source code so we don't have to guess what you need.
I had the same issue but fixed it with a localBroadcastReceiver like this:
Create a receiver in your activity and register it:
/**
* ******************************
* Receiver to process the message
* *******************************
*/
private BroadcastReceiver onNotice = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//You can send any extra data if you need like this
final int type = intent.getIntExtra("fragment.data", -1);
Log.d(tag, "main class: " + type);
//also refresh your fragment like this
mViewPager.getViewPager().getAdapter().notifyDataSetChanged();
}
};
#Override
protected void onResume() {
super.onResume();
//Register a localbroadCast with the your filter
IntentFilter thinaireFilter = new IntentFilter("your.filter");
LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, thinaireFilter);
}
Remember to remove LocalBroadCast
//remove the LocalBroadCast when no need it
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}
Send your broadcast from anywhere you want Adapters, services, etc.
Intent sendBroadCastData = new Intent("your.filter");
sendBroadCastData.putExtra("fragment.data", myData);
LocalBroadcastManager.getInstance(context).sendBroadcast(sendBroadCastData);
Hope it helps others.
I don't know enough of what you are doing, but it sounds like you need to use an Observer pattern, Callbacks, or Listeners. Can't your fragment just do somthing like:
myservice.addMyEventListener(myFragInstance);
and then you can be "notified of a specific event."
Just look at this answer https://stackoverflow.com/a/16388650
He has used yourAdapter.notifyDataSetChanged() which is a predefined method.
Check the link to see how its done
Edit:
When your AsyncTask is done, you should do something like this onPostExecute method:
ResultFragment resultFrag = (ResultFragment) getSupportFragmentManager()
.findFragmentByTag("FragToRefresh");
if (resultFrag != null) {
resultFrag.refreshData(refreshedArray);
}
And in your ResultFragment you need to have refreshData method, which is something like this:
public void refreshData(ArrayList<YourObject> data) {
yourArray = new ArrayList<YourObject>(data);
yourAdapter.notifyDataSetChanged();
}
Had to use event bus to make everything simple https://github.com/greenrobot/EventBus
I am not sure this is the right way of doing it
1. Create a public function in fragment you would call to receive the data.
public void refreshList(List<String> yourData) {
//referesh your fragment views here
}
2. Create the fragment object global
YourFragment frag = new YourFragment();
3. Pass it to the view pager in the containing activity
4. Add on page change listener to the view pager
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
break;
case 1:
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Here case 0: would be invoked when first fragment is selected and case 1: when second and so on..
5. Call your function corresponding to its position in the view pager
case 0: frag.refreshList(yourList);

Categories

Resources