I have the following code
public abstract class BaseAdapter<T, V extends BaseAdapter.ViewHolder> extends ArrayAdapter<T> {
public BaseAdapter(Context context, int resource, Collection<T> collection) {
// typical constructor logic
}
// some other custom defined methods
public static class ViewHolder {
// custom defined logic
}
}
public class ModelAdapter extends BaseAdapter<Model, ModelAdapter.ModelViewHolder> {
public ModelAdapter(Context context, int resource, Collection<Model> collection) {
super(context, resource, collection);
// typical constructor logic
}
public static class ModelViewHolder extends ViewHolder {
// custom defined logic
}
}
The BaseAdapter and ModelAdapter are in separated files. The problem is that I have a compilation error when trying to define the ModelAdapter: ModelViewHolder is not accessible in current context
I don't really understand this error and can't figure out what I am doing wrong. Can somebody explain to me this problem or a link that may clarify this situation?
Creation Dead Lock
You use
ModelAdapter.ModelViewHolder
as the template parameter ofBaseAdapter
, and letModelAdapter
extendsBaseAdapter
, then the compiler tried to createModelViewHolder
first, but the class ofModelAdapter.ModelViewHolder
(the type is Class) is not yet created. It must wait forModelAdapter
to be created, becauseModelViewHolder
is in the scope ofModelAdapter
.The way to solve it is put the
ModelViewHolder
class into a new *.java file.I faced this issue before, I'm not sure why that happened,
but I resolved it by
Here's how it got resolved for me. Generally there shouldn't be a circular dependency problem, as the nested viewholder classes are static. E.g. look at the notorious
LayoutParams
hierarchy, which is built exactly the same way: a class inherits another class and then their static nested classes have corresponding inheritance relationship.It looks like the circularity comes rather from the visibility scope issue.
ModelViewHolder
may extendViewHolder
only as it gets to know it after the outerModelAdapter
inheritsBaseAdapter
's visibility scope. MeanwhileModelAdapter
cannot inheritBaseAdapter
untilModelViewHolder
class is initialised as it needs for the generic parameter. On the other hand,ModelViewHolder
is a static nested class and doesn't technically depend on its outer class.Thus, the solution is to fully qualify the
ViewHolder
's name when declaringModelViewHolder
. Note theextends BaseAdapter.ViewHolder
part in the snippet below. This way,ModelViewHolder
doesn't need to useModelAdapter
's scope to know aboutViewHolder
.ModelAdapter.java
A note about Android Studio: Even though the issue itself isn't related to Android Studio, I ran into it by using AS's "Copy class" feature (using AS 3.0). While copying, it "simplified" the code for me, removing the fully qualified name. So, watch out for AS's smartness!
Happened the same to me when extending a Base class. But this time I had it like this (following the given example in the question)
BaseAdapter.java
ModelAdapter.java
That way the warning was gone and didnt need to separate ModelViewHolder into another '.java' file. Notice that they are in two different files and the import in ModelAdapter.java.
I think Fei Liang's answer is partially incorrect because being ModelViewHolder static should make possible to initialize ModelViewHolder without initializing its parent class ModelAdapter