I know JAVA's generic concept = type
and Android's Recycler View concept.
I already know this -> extends RecyclerView.Adapter. have seen from the Android developer site.
But, this is still difficult to understand.
I was looking at Firebase's Cloud Firestore code.
And some codes...
extends FirestoreAdapter<SomeClassAdapter.ViewHolder>
and
public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH>
these concepts are so difficult for me...
some generics and something extends in there.
I've done a lot of searches and I've done a lot of thinking. Can you explain easily, please?? or some sites to refer.
Thanks for reading! any kind of tip does not matter. I`ll appreciate!
Perhaps it would be easier to understand if I explain this with an example:
Assume we have an adapter class named SomeClassAdapter which has an inner class called ItemViewHolder as below:
public class SomeClassAdapter extends FirestoreAdapter {
...
private class ItemViewHolder extends FirestoreAdapter.ViewHolder {
...
}
}
If we want to extend SomeClassAdapter using the inner class (ItemViewHolder) as our view holder we would use:
public class Example extends FirestoreAdapter<SomeClassAdapter.ItemViewHolder>
But the second concept you mentioned is the super class which we extend in our example (it's abstract and we have to extend it and override its abstract methods in order to make an instance)
Now assume we have a class which requires a type to use it across the class declaration. In that case we declare a class like FirestoreAdapter and pass the generic type inside <..> like: FirestoreAdapter<VH>. In case we need our VH to be a sub type of another class like RecyclerView.ViewHolder we declare it as: FirestoreAdapter<VH extends RecyclerView.ViewHolder>.
And what if we need our FirestoreAdapter itself to be a sub type of another class such as RecyclerView.Adapter? So it would be FirestoreAdapter<VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter. In our example the RecyclerView.Adapter class needs a generic type extending RecyclerView.ViewHolder itself and we want to use the same type we used for FirestoreAdapter<VH> here so we simply pass VH as our generic type for RecyclerView.Adapter. And to come into a conclusion we'll have:
FirestoreAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH>
Immediate translation.
Translated to human speak we get this, The generic FirestoreAdapter will only except parameterized types of ViewHolder or its subclasses. Finally it will inherit all of the available fields from its super class, which is the generic class RecyclerView.Adapter
Proof and documentation is down below.
< VH extends RecyclerView.ViewHolder >
This is part is utilizing Bounded Type Parameters
Why use Bounded Type Parameters?
Well the documentation states:
There may be times when you want to restrict the types that can be used as type arguments in a parameterized type.
Before we move on it is important that we define type type arguments and parameterized type
What are type arguments?
As stated in the documentation :
Many developers use the terms "type parameter" and "type argument" interchangeably, but these terms are not the same. When coding, one provides type arguments in order to create a parameterized type.
We can then map this definition over to our code to understand that our own CustomAdapter.ViewHolder acts as a type arguments . Now we can move on.
What is a parameterized type?
Well the Documentation states
We can think of parameterized types as formal instantiations of our type arguments To instantiate this class, use the new keyword, as usual, but place between the class name and the parenthesis:
Box integerBox = new Box();
What is < VH extends RecyclerView.ViewHolder > doing?
The documentation states :
To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound
Now type parameters are simply anything that goes inside the angle brackets <>. Source
With that being said we can come to the conclusion that VH is nothing more that a type parameter and extends RecyclerView.ViewHolder is saying that our generic class only accepts ViewHolder objects or its subclasses.
Conclusion
public abstract class FirestoreAdapter
extends RecyclerView.Adapter
translates to, The generic FirestoreAdapter will only except parameterized types of ViewHolder or its subclasses. Finally it will inherit all of the available fields from its super class which is the generic class RecyclerView.Adapter
Related
I had Android Studio convert my code for an OnClickListener.
Obviously a lambda is used here. What I don't know is whether the lambda is passed to a function of the View class or to the constructor of the OnClickListener class.
I have already looked in the Android documentation for a method with the name OnClickListener in the View class but found nothing.
If the latter is the case, I don't understand how an instance of the OnClickListener class can be created even though it is an interface.
val onClickListener = View.OnClickListener { refreshListView() }
The class OnClickListener is an inner class of the View class:
https://developer.android.com/reference/android/view/View.OnClickListener
Inner classes are identified by a '.' in their classname, on byte code level they are separated with a '$' instead.
With the invocation as written in your question you create an anonymous class implementing the functional interface and implementing its onClick(View) method. You can do the same in Java with a bit more verbose syntax, but technically the same.
What is the reason behind it ?
Is it for performance or compulsion?
Please Explain
First, we need to understand one thing about Abstract Classes in that they allow you to skip implementing some default methods of the parent class.
Unlike Interfaces where you implement all the interface methods, in Abstract Classes world the child classes can choose to implement what is specific to the child class and leave out the other implementations if not needed.
If you do a deep dive on the parent RoomDatabase documentation you will note that it is the Base class for all Room databases and it has some methods not relavant to the child classes e.g. createOpenHelper(), createInvalidationTracker(), clearAllTables().
In fact the docs clearly mention that 'RoomDatabase provides direct access to the underlying database implementation but you should prefer using Dao classes'.
In simple terms, you should mark your RoomDatabase class as Abstract to enable your class become flexible and skip implementing unnecessary methods of the RoomDatabase Base Class.
This is true because when you don't mark the class as Abstract, you will get an error and Android Studio will prompt you to implement the above Base Class methods.
So in Kotlin you will do something like this:
#Database(entities = [Note::class], version = 1)
abstract class NoteDatabase :RoomDatabase() {
//Property must be initialized or be abstrac
abstract val noteDAO:NoteDAO
}
Here the NoteDatabase inherits from RoomDatabase to make it a RoomDatabase Object- it doesn't need parent's default implementations therefore it skips those because it is marked with Abstract.
NoteDatabase only needs to declare the an abstract noteDao variable. This is so that NoteDatabase knows about DAO Interface and this variable is also used for testing.
Because RoomDatabase has defined methods, the inheriting class cannot be an interface. And because you write your undefined method in that abstract class, it cannot be a class.
public interface MyDatabase extends RoomDatabase // extend is not allowed for interface
public class MyDatabase extends RoomDatabase {
public abstract MyDao myDao(); // abstract method is not allowed for non abstract class
}
Because Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
Room is an ORM, Object Relational Mapping library. In other words, Room will map our database objects to Java objects. Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
When a class extends an abstract class, it needs to override all its abstract methods. But, in our case we don't need to implement abstract methods of RoomDatabase class. So, to overcome that we need to make our Room database class abstract.
abstract class ABC{
public abstract void methodA();
public abstract void methodB();
public abstract void methodC();
}
public class OurClass extends ABC{
public void methodA(){
System.out.println("Only methodA implementation");
}
}
This will give compile time error.
Solution 1: Implement all abstract methods of the Parent class in SubClass.
Solution 2: (Our case) Make SubClass abstract.
Consider using abstract classes if any of these statements apply to your situation:
You want to share code among several closely related
classes.
You expect that classes that extend your abstract class have
many common methods or fields, or require access modifiers other than public (such as protected and private).
You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the
object to which they belong.
I am getting below compilation error
Realm model classes must either extend RealmObject or implement
RealmModel to be considered a valid model class
In this particular scenario
class Animals extends RealmObject {
}
class Dog extends Animals {
}
I am getting this error for the Dog class.
That error appears when I am indirectly extending RealmObject. i.e Dog is extending Animals (which in turns extends RealmObject), not RealmObject directly.
Inheritance / Polymorphism is still an open issue in Realm,
Check this link https://github.com/realm/realm-java/issues/761
While the issue has not been closed yet, it is recommended to use composition instead of inheritance: F.ex. you could have
public interface Animalistic {
makeNoise();
}
which is then implemented by each animal.
Let's say I have the following class structure
public class SipService implements Parcelable{
public SipCore sipcore;
public PhoneRinger phoneringer;
public CurrentML currentml;
public AManager amanager;
//etc...
}
All the properties of SipService are non-parcelable classes. And the properties of those properties are non-parcelable classes. And the properties of those properties of those properties are non-parcelable classes. And the properties of those properties etc.... are non-parcelable classes.
I do not have access the to the source code for any of those classes of the properties of SipService.
Does this mean that SipService can not successfully implement Parcelable?
Because you don't have access to all the member variables of the classes and can't change this, you can't make SipService parcelable.
If you would have access, you could read all the variables of the classes in your SipService and make a new instance of them. But for that you need the getters and a appropriate constructor for each class to rebuild them.
If these classes are implementing the Serializable interface, you could make it serializable. Because it's behaving pretty much the same, but the performance is better if the class implements parcelable.
OR
If you can talk to the team, suggest them to implement the parcelable/serializable interface if it's a reasonable requirement.
I'm new to java and android development. After spending few days working with java I started with android development. I've this question with regards to the Context class.
Context is a abstract class. Which cannot be instantiated and cannot be used to call methods unless it refers to a concrete subclass. Can someone tell how the call getApplicationContext which returns a context type is used in applications (a small snippet of how will be a huge help).
And also help me understand this statement Context context = getApplicationContext() getApplicationContext is an abstract method so when we use this call, which object implements this? Is it the ContextWrapper object of the current process (app) that gives this method.
Thanks in advance.
The activity you're implementing inherits from Activity, which in turn inherits from Context. There are a few more classes on the way and one of them implements getApplicationContext() for you.
An abstract class cannot be instantiated, but can be inherited and any (or most...) class that fully implements all of its abstract methods can be instantiated. You can then reference instances of those classes as the abstract class for abstract handling. If you go with the good old employee example, when you calculate total salary, you don't care if the employee is a manager or a salesman.
// Employee is an abstract class with an abstract method - getSalary()
a = new ArrayList<Employee>();
a.add(new Manager())
a.add(new Salseman())
for (Iterator i = list.iterator(); i.hasNext();)
{
Employee e = i.next();
System.out.println(e.getSalary());
}