Access Inner Class Method (from Viewholder in adapter) from a Fragment - java

I have a fragment lets call it EventFragment, and I have an RecyclerView.Adapter called EventAdapter, inside that adapter is a viewholder class called EventViewHolder. I want access an animation method inside the viewholder class from the Fragment.
How would I accomplish this? I was thinking to define another interface to accomplish this.
This is what I have so far:
OnAnimationListener
public interface OnAnimationListener {
void onAnimation();
}
Adapter
public EventAdapter extends RecyclerView.Adapter<RecycleView.ViewHolder> {
// Boilerplate initialization stuff here
public class EventViewHolder extends RecyclerView.ViewHolder implements OnAnimationListener {
// Initialization code
#Override
public void onAnimation() {
// Do an animation
}
}
}
EventFragment
public class EventFragment extends Fragment {
// Boilerplate initialization code
}
I am thinking I should implement an interface inside the Fragment like so:
public class EventFragment extends Fragment implements onAnimationListener {
private void initAdapter() {
mAdapter.setOnAnimationListener(this);
}
#Override
public void onAnimation(Data data) {
// pass any data
}
}
Then I'm sort of stuck at this point. Normally you would call this once the listener is passed through:
OnAnimationListener.onAnimation(...)
But this doesn't make sense. The code flow goes like this:
EventFragment --> Adapter --> ViewHolder
I need to implement the following code flow:
EventFragment (get access to specific viewholder and do animation) <--> Viewholder
How should I accomplish this? Maybe pass the interface from the Viewholder to the Fragment instead, and call mOnAnimationListener.onAnimation() from the fragment right?
I want to have specific control of when the animation occurs on the EventViewHolder and I want to have this control from the EventFragment how should I go about tackling this?

If you simply want to animate the RecyclerView's items you can take a look at RecyclerView.ItemAnimator.
If not (or if you still want to handle this in the fragment) you can attach click listeners for your views inside the ViewHolder object and handle the clicks by passing the event up ViewHolder->Adapter->Fragment via the mechanism you already have (and passing the view received in onClick as a parameter). Personally I'd stay away from this pattern. One reason being that the RecyclerView can be scrolled in the meantime and I don't have enough knowledge right now on what happens to that particular view once it's off position or maybe even off screen. Or maybe pointing to other data.

Related

Can't understand use of this keyword in View.setOnClickListner(this)?

I know that keyword this refers to current instance of class. But When we implement View.OnClickListener in our class then on calling method textview.setOnClickListener(this), How does argument this(instance object of class) of setOnClickListener(this) call automatically onClick() method. Is there any code in view class which take object and call onClick method on this code or something else is going on?
I want to know what is going behind the scenes, how does android reaches from this keyword to onClick() method? That is what I want to ask?
OnClickListener is an interface in class View.
If your activity implements this interface by setting:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
then you can set a listener for a view like button:
myButton.setOnClickListener(this);
and override the onClick method implementing it like this:
#Override
public void onClick(View v) {
// your code here
}
so a simple explanation is: this means that your view will use your activity's overridden onClick method.
To implement the View.setOnclickListener in your code you need to first implement the public static interface View.OnClickListener.
like this
public class MyActivity extends Activity implements View.OnClickListener {
}
The above interface contains public void abstract method "onClick(View v)" which you override to put your logics
This method is called when a view has been clicked.
for sake of simplicity i have created the code
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
here OnclickListener is an interface which have object mCorkyListener
similarly you can use this keyword instead mCorkyListener
‘this’ represents the instance of the current class. You can access the properties and functions of the current class with ‘this’ keyword.
Let's have an interface ElectricityBill
public interface ElectricityBill{
public void pay(int amount);
}
now there are two ways you can pay an electricity bill either by going to nearby electricity board office
ElectricityBill bill = new ElectricityBill(){
#Override
public void pay(int amount){
}
}
payBill(bill);
or by paying the bill online
public class User implements ElectricityBill{
.....
#Override
public void pay(int amount){
}
}
.....
payBill(this);
}
in both the cases, the user has to pay XXX amount, similar is the case if you want to listen to input events you either have to pass the original View.OnClickListener object or implement it and pass this to make it work.
Edit:
when you pass this you tell the current class to handle the click events itself and has to override the onClick() to do so. And when you pass object you let the original class to handle the onClick by creating an anonymouse class and implementing onClick(). but when you pass this your current class get's the authority to listen to input events. It becomes on the type of OnClicklistener and gets the authority to listen onClick()

inheritance of viewholder class

I'm an android developer and I've got this issue regarding some OOP concepts in android. Whenever we create an adapter (lets take a recycler adapter ..) I usually do something like this:
public class MyAdapter extends RecyclerView.Adapter<"MyAdapter.MyViewHolder">
{
public MyAdapter(){}
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){}
public void onBindViewHolder(MyViewHolder holder, int position){}
public class MyViewHolder extends RecyclerView.ViewHolder{}
My question is in case we have our MyViewHolder as an internal class in our adapter (like written above....), why does it have to be declared as public/protected ?? Anytime I try to make the class private,I get an error at the top of the adapter class: 'packagename.MyAdapter.MyViewHolder has a private access in packagename.MyAdapter'
Ever since i've been looking at tutorials (text or video) which explain how adapters work, they have never tried to explain why the MyViewHolder class needs to be declared as public. I really wanna understand this stuff.

Call a method in MainActivity.java on event that happens in a library file

I included the library Swipeable-Cards in my android project. In MainActvitiy.java the onCreate method includes something like that:
SimpleCardStackAdapter adapter = new SimpleCardStackAdapter(this);
//This should also be done on an event in the library class:
adapter.add(new CardModel("Title2", "Description2 goes here", r.getDrawable(R.drawable.picture2)));
Now, in the CardContainer.java (which belongs to the swipeable cards library) there is an event on which I want a new item added to the adapteradapter.add(...). The adapter was defined in the MainActvitiy.java as you can see above.
How can I achieve this?
I first thought about defining a new method in MainActivity and then calling it from my library-class, like that:
public void callfromlibrary() {
adapter.add(...);
}
However then the method and the adapter need to be defined static, additionally I don't know how to make this method of MainActivity available in CardContainer.java.
I believe I need to create kind of a listener to check in the MainActivity what happens in CardContainer.java? I don't know how to do this.
Any help is appreciated!
To allow CardContainer to communicate up to the MainActivity, you define an interface in CardContainer and implement it in MainActivity. When the event occurs in CardContainer, it can then call Interface method in order to add the CardModel to the adapater.
public class CardContainer extends ... {
CardContainerEventListener mCallback;
// Define a interface
public interface CardContainerEventListener {
public void addToAdapter();
}
// Method to register callback
void registerCallback(Activity callback) {
mCallback = (CardContainerEventListener) callback;
}
void someFunction() {
// Event got generated, invoke callback method
mCallback.addToAdapter();
}
}
public class MainActivity extends Activity implements CardContainer.CardContainerEventListener {
// Ensure you register MainActivity with CardContainer, by calling
// cardContainer.registerCallback(this)
public void addToAdapter() {
adapter.add(...);
}
}
please use a Java Interface for achieving this..
declare an interface in the cardcontainer class
public interface yourInterface{
public void callfromlibrary();
}
and intialize the object for calling the function
yourInterface object = (yourInterface) MainActivity;
and implement the interface in your main activity like
Class MainActivity extends activity implements yourInterface
and implement callfromlibrary() method
call this method from cardcontainer class whenever you needed using the object you have created ..
object.callfromlibrary()

Adapter.getItem(position) crashes application

I'm writing an Android Application with a custom Adapter for a list view.
The adapter is a variable in the mainActivity class and contains a list of custom classes. I need to access a class in this list from an other activity, but the application seems to crash when it reaches getItem(position) in the adapter.
Basically this is what the application looks like:
in the MainActivity class there is a basic custom adapter:
public class MainActivity extends Activity {
public static MyAdapter myAdapter;
...
}
The adapter only has the basic functions like getItem and has a list of custom (basic) classes
public class MyAdapter extends BaseAdapter {
private ArrayList<MyClass> tours = new ArrayList<MyClass>();
#Override
public Object getItem(int arg0) {
return getItem(arg0);
}
...
}
When the other activity is opened, an index is passed to it to access a certain Object from the list.
The only problem is that when I try to access a class from this list, the application crashes...
I used following code to access the class from the list in the adapter:
MyClass myClass = (MyClass)MainActivity.myAdapter.getItem(index);
Can someone tell me what I'm doing wrong or why the app crashes?
This is recursive logic:
#Override
public Object getItem(int arg0) {
return getItem(arg0);
}
There's no way for this method to complete, it simply calls itself again and again until the app throws some type of overflow exception. It should be:
#Override
public MyClass getItem(int arg0) {
return tours.get(arg0);
}
Notice how this method returns data from your List.

How do I register for an event on an object without the need for an anonymous class?

I'm creating an android app. I have a Dialog, and I want to handle the onCancel() event without using an anonymous class because it's cleaner and there are class variables I need access to from the main Activity class. I'm looking for a way to register for events on an object similar to .NET, where I can handle it in a separate method in the class without the need for an anonymous class.
There is a nice example here in the Event Listeners section.
The first example uses an anonymous class for the listener; the second uses a method inside the Activity. No extra class needed.
TL;DR Here is the code stolen from that page:
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
You can modify this to use onCancel().

Categories