Call notifyDataSetChanged() within Fragment - java

I'm using ViewPager in MainActivity.java with five Fragments.
Now I've got a problem.
Running notifyDataSetChanged() works fine like this:
viewpager.getAdapter().notifyDataSetChanged();
But how can I run notifyDataSetChanged() from a Fragment?
I have no idea.
What I've tried
Making ViewPager static and then run
MainActivity.this.viewpager.getAdapter().notifyDataSetChanged()
doesn't work.

Add a method to your MainActivity like
public void dataChanged() {
viewpager.getAdapter().notifyDataSetChanged();
}
and from your fragments call it with
((MainActivity) getActivity()).dataChanged();

You can do this by various methods:
The easiest one - declare a public method in MainActivity.java as following:
public void onDataSetChanged(){
if(viewPager != null) {
viewPager.getAdapter().notifyDataSetChanged()
}
}
And then call it from the fragment like this:
((MainActivity) getActivity()). onDataSetChanged();
Using Interface: You can create your own interface as :
public interface OnDataSetChangeListener {
void onDataSetChanged();
}
Declare and define an instance of it in MainActivity.java and then set it to the instance of your fragment. Then call it from fragment as:
onDataSetChangeListener.onDataSetChanged();
Using EventBuses.
And many more.

Related

How to call method from fragment only if host activity was destroyed?

I got a method() in the fragment. Fragment in host activity. So I need to call the method() from fragment ONLY when host activity was in onDestroy() . Maybe it suppose to be something like a static flag?
You can, by SupportFragmentManager, get a Fragment by layout id, tag or name.
But the most important thing here is in some situations Activity.onDestroy() method could never be called. So be careful if you implement code that needs to be executed, like an unsubscribe logic or removing callbacks.
class MyActivity: AppCompatActivity() {
override fun onDestroy() {
super.onDestroy()
val fragment = supportFragmentManager.findFragmentById(R.id.my_fragment) as MyFragment
if (fragment != null) {
fragment.myMethod()
}
}
}
class MyFragment: Fragment() {
fun myMethod() {
}
}
Or use a ViewModel to handle communication between the activity and the fragment.
https://developer.android.com/topic/libraries/architecture/viewmodel#sharing

Getting null value in fragment spinner

I am trying to use filter in Fragment and implementing the dialog fragment.
This is the class that I am using
public class HomeFragment extends Fragment implements
FilterDialogFragment.FilterListener,
PostAdapter2.OnPostSelectedListener{ detail code }
this the dialogfragment based class for spinner choosing options
public class FilterDialogFragment extends DialogFragment
this method is called upon clicking the filter button, which pops up dialog for spinner options of the filter
Declared
private FilterDialogFragment mFilterDialog;
in onCreateView
mFilterDialog = new FilterDialogFragment();
Method to call
public void onFilterClicked(){
mFilterDialog.show(getSupportFragmentManager(), FilterDialogFragment.TAG);
}
after this upon selecting the spinner option and clicking apply this method is called in which mFilterListener is null which should not be the case
public interface FilterListener {
void onFilter(Filters filters);
}
FilterListener mFilterListener;
public void onSearchClicked() {
Log.d("Message", String.valueOf(mFilterListener));
if (mFilterListener != null) {
Log.d("Message", "New 55555");
mFilterListener.onFilter(getFilters());
}
dismiss();
}
please assist me to solve this problem. if anymore details are required please let me know
attach method in FilterDialogFragement
public void onAttach(Context context) {
super.onAttach(context);
Log.d("Message", "New 6666666");
Log.d("Message", String.valueOf(mFilterListener));
if (context instanceof FilterListener) {
// Log.d("Message", String.valueOf(mFilterListener));
mFilterListener = (FilterListener) context;
}
}
You are attempting to mimic this library implementation: Friendly Eats.
However, you do not copy it wholesale, mainly in that you choose to use HomeFragment which implements FilterDialogFragment.FilterListener to launch FilterDialogFragment, rather than the library's MainActivity. This is the cause of your null pointer.
This is due to how getSupportFragmentManager() works. If you look at Android's documentation for this, you will see it says
Return the FragmentManager for interacting with fragments associated with this activity. (My Bolding)
When you call mFilterDialog.show(getSupportFragmentManager(), FilterDialogFragment.TAG); inside HomeFragment, you are actually calling whatever Activity that is the parent of HomeFragment to launch the new FilterDialogFragment. You could double check this by checking if, in onAttach(Context context) inside HomeFragment, if context instanceof HomeFragment. I do not think it will return true.
To solve this, and without changing your use of HomeFragment, you could simply pass an instance of HomeFragment itself, or a separate implementation of FilterDialogFragment.FilterListener (which I'd prefer if you do not need to use anything from HomeFragment other than the listener) to your FilterDialogFragment instance on creation or before you launch it.
For example, you could create a public setter like so:
private FilterListener mFilterListener;
public void setFilterListener(FilterListener filterListener){
mFilterListener = filterListener;
}
and then in your HomeFragment onCreateView(), you do this:
mFilterDialog = new FilterDialogFragment();
//Or preferably, an anonymous/named implementing instance of the interface only.
mFilterDialog.setFilterListener(this);
Doing so would not rely on the Android framework to provide the initialisation of your field, and does not require you to either change your Activity or HomeFragment you are currently using.
I assume, that u didnt set the listener in a mFilterDialog, so thats why its null

Calling activity function from class

I'm using Kotlin in android studio to make an app.
In my main activity I have a function changeText() that changes the text of a textbox.
I have a class that I'm implementing called VerificationListener() that when created will do things then call onVerified(), however I cannot call changeText from onVerified, is there a way to do so? The example I'm working off of is in Java and does it.
Example I'm working off of
public void onVerified() {
mIsVerified = true;
Log.d(TAG, "Verified!");
hideProgressAndShowMessage(R.string.verified);
showCompleted();}
Above is within the class, below is just sitting in the activity
private void showCompleted() {
ImageView checkMark = (ImageView) findViewById(R.id.checkmarkImage);
checkMark.setVisibility(View.VISIBLE);
}
If by "I cannot call changeText from onVerified" you mean that you have a VerificationListener as a separate standalone class and from that class you cannot call methods on the Activity, you should either a) make the VerificationListener an inner class of the Activity, b) pass your activity into the VerificationListener when it's created (be aware of the lifecycle) c) implement some messaging solution (broadcast receiver, startActivity + onIntent(), observable, or even an event bus (not advisable). Here is a sample implementation for b:
class MyActivity : Activity(), VerificationListener.OnVerifiedCallback {
fun onVerified() {
changeText()
}
override fun onCreate(state: Bundle) {
super.onCreate(state)
VerificationListener(this).doStuff()
}
}
class VerificationListener(internal var callback: OnVerifiedCallback) {
interface OnVerifiedCallback {
fun onVerified()
}
fun whenSomethingGetsVerified() {
doThings()
callback.onVerified()
}
}
EDIT: forgot you are using Kotlin, changed to Kotlin implementation
You can't access the UI from a background thread, Kotlin or not. You have to run this on the UI thread:
runOnUiThread {
val checkMark: ImageView = findViewById(R.id.checkmarkImage)
checkMark.visibility = View.VISIBLE
}

Pass data from activity to a non-fragment/activity class without using an interface

public boolean getFavourite(Winkel winkel){
boolean isFavourite = false;
MyDBHandler dbHandler = new MyDBHandler(context,null,null,1);
User user = dbHandler.loggedIn(); //This method isn't usable anymore
isFavourite = dbHandler.isFavourite(user,winkel);
return isFavourite;
}
I want to change this code to:
public boolean getFavourite(Winkel winkel){
boolean isFavourite = false;
MyDBHandler dbHandler = new MyDBHandler(context,null,null,1);
isFavourite = dbHandler.isFavourite(user,winkel);
return isFavourite;
}
I was using my database to keep track of which user was logged in at first, but it was really easy to change this by simply sending the data from my first activity to my second.
#Override
public void login(User user){
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("Username",user.getUserName());
startActivity(intent);
}
Then, in my second activity, I could call all the database functions by using this:
user.setUserName(intent.getStringExtra("Username"));
(Because I need the username as a key for my database.
However, my activity has three fragments, two of which use my adaptor for a recyclerview. These fragments implement the interface that is provided in my adaptor class, which is this one (just showing this to be complete, what the interface is is irrelevant, fact is that my fragments have to implement this interface).
public interface ItemCLickCallback {
void onItemClick(int p);
void onSecItemClick(int p);
}
Now, I need the username in my adaptor class. It has to come from my activity (because thats where its stored), and I can't use an interface because I'm already using one and I would have to override the methods in every fragment.
I could pass the data from my activity to all the fragments using a Bundle, then pass that along to the adaptor when creating it in my fragments. But that seems like a lot of excessive code. Any simpler way to do this? Thank you
EDIT:
In Adaptor class:
private CheckFavourite checkFavourite;
public void setCheckFavourite(final CheckFavourite checkFavourite){
this.checkFavourite = checkFavourite;
}
boolean isFavourite = checkFavourite.getFavourite(winkel);
public interface CheckFavourite{
boolean getFavourite(Winkel winkel);
}
Fragment:
public class Overview extends Fragment implements Adaptor.ItemCLickCallback
Activity:
public class SecondActivity extends AppCompatActivity implements Adaptor.CheckFavourite
Activity has to implement the seconde interface, fragment implements the second. But both of them are on the same adaptor instance.
What I need to do (in my activity basically):
adaptor.setCheckFavourite(this);
But I can't because I don't have the adaptor there, it gets created in my fragment.
I tried:
adaptor.setCheckFavourite(this.getActivity());
in my fragment, but that gives me an an error:
Error:(60, 51) error: incompatible types: FragmentActivity cannot be converted to CheckFavourite.
However
adaptor.setItemCLickCallback(this);
is working perfectly fine in my fragment (the other interface). How do I fix this?
:) You can use multiple inheritance. To be able to make a class implement multiple interfaces we need can have something like this:
public class MyClass extends MyOtherClass implements MyInterface1, MyInterface2, ... , MyInterfaceN {
// Need to implement all interface methods here
}

setOnClickListener to all extended ImageViews - Java

I have a custom class that I've written that extends ImageView (for Android Java). I want to add a ClickListener to every instance I create of the class that will do the same thing (just animate the ImageView.
I tried a few different things to no avail. The code below is what I want to accomplish but it's being applied to an instantiated object of the class.
MyCustomImageView fd = new MyCustomImageView(this);
fd.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Animater(fd);
}
});
I tried using "implements onClickListener" on the class declaration and then a public void onClick() method in the class, and that didn't work for me.
I also tried using the code snippet above with a "this" instead of "fd" and that didn't work either.
I'm relatively new to java and this is out of the scope of my knowledge. Any assistance you can provide is greatly appreciated.
It's really easy. You have to do it in your custom class:
public class MyCustomImageView extends ImageView{
public MyCustomImageView(Context context){
super(context);
setOnClickListener(theCommonListener);
}
private OnClickListener theCommonListener = new OnClickListener(){
public void onClick(View v) {
// do what you want here
}
}
}
There are other ways to do it, but this is one is really easy to implement and understand. Every instance of MyCustomImageView will have the same event listener (unless you override it from outside).

Categories