[英]Convert custom adapter to use generics in Java
I have a Adapter in my Android app and I want to make it Generic. 我的Android应用程序中有一个适配器,我想使其通用。
Basiclly the Adapter looks like that: 适配器基本上是这样的:
public class myAdapter extends FragmentStatePagerAdapter {
DataTypaA myFragment;
DataTypeB data;
DataTypeC items;
public myAdapter(FragmentManager fm, DataTypaA fragment) {
data = new SparseArray<DataTypeB>();
myFragment = fragment;
items = myFragment.getData();
}
public DataTypeB getItem(int position) {
return data.get(position);
}
@Override
public int getCount() {
return items.getList().size();
}
public void setData () {
items = myFragment.getItems () //getItems return DataTypeC
data.setTheData (items)
}
}
I changed it to generic 我将其更改为通用
public class myAdapter <A,B,C> extends FragmentStatePagerAdapter {
A myFragment;
B data;
C items;
public myAdapter(FragmentManager fm, A fragment) {
data = new SparseArray<B>();
myFragment = fragment;
items = (C) myFragment.getData();
}
public B getItem(int position) {
return data.get(position);
}
@Override
public int getCount() {
return items.getList().size();
}
public void setData () {
items = myFragment.getItems () //getItems return DataTypeC
data.setTheData (items)
}
}
but I'm getting different errors, when methods should get DataTypeC
parameter and I passing it parameter type C
( data.setTheData (items)
) that is actually type DataTypeC
the compiler suggest to cast C
to type DataTypeC
. 但是我遇到了不同的错误,当方法应该获取
DataTypeC
参数并向其传递参数类型C
( data.setTheData (items)
),而该参数类型实际上是DataTypeC
,编译器建议将C
转换为DataTypeC
。 and in getCount()
I have also error suggesting to convert items
to DataTypeC
. 在
getCount()
我也有错误建议将items
转换为DataTypeC
。
for example when I try to override getItem I getting mistakes, but when I create the same method with other name it compiles. 例如,当我尝试覆盖getItem时,我会出错,但是当我使用其他名称创建相同的方法时,它将编译。
//Error - "The return type is incompatible with FragmentStatePagerAdapter.getItem(int)"
@Override
public B getItem(int position) {
return (B) data.get(position);
}
//compiles
public B getItemTest(int position) {
return data.get(position);
}
Any ideas how to fix it so it will be 100% generic? 任何想法如何解决它,使其成为100%通用的?
ADDED : After your answer I changes it to support return of generic type : 添加 :在您回答之后,我将其更改为支持通用类型的返回:
public class TypeA <T> {
private T mData;
public T getData() { return mData;; }
}
public class myAdapter <A,B,C> extends FragmentStatePagerAdapter {
A myFragment;
B data;
C items;
public myAdapter(FragmentManager fm, A fragment) {
data = new SparseArray<B>();
myFragment = fragment;
items = myFragment.getData(); //Error - The method getData() is undefined for the type T
}
}
I'm getting compile error... when I run it of course <T>
and <C>
are the same type. 我遇到了编译错误……当我运行它时,
<T>
和<C>
当然是同一类型。
The first problem is that your non-generic code doesn't compile. 第一个问题是您的非通用代码无法编译。 You have a field
DataTypeB data;
您有一个字段
DataTypeB data;
which you then assign a SparseArray<DataTypeB>
to. 然后将其分配给
SparseArray<DataTypeB>
。 Also, setData
doesn't compile at all. 另外,
setData
根本不编译。
Ignoring this... you have declared type parameters A, B, C
and changed your instance field types, but you still try and assign DataTypaA
to A myFragment
in your constructor, and a SparseArray<DataTypeB>
to B data
. 忽略此...您已经声明了类型参数
A, B, C
并更改了实例字段类型,但是您仍然尝试将DataTypaA
分配给DataTypaA
中的A myFragment
,并将SparseArray<DataTypeB>
分配给B data
。 When you migrate code to generics you need to approach it like you would refactoring - one step at a time. 当您将代码迁移到泛型时,您需要像重构那样进行处理-一次仅一步。
For instance, by diving in as you have now take a look at items = (C)myFragment.getData()
. 例如,通过现在进入,可以查看
items = (C)myFragment.getData()
。 As fragment
is still of type DataTypaA
then presumably its getData()
method doesn't return a generic type. 由于
fragment
仍然是DataTypaA
类型, DataTypaA
大概它的getData()
方法不会返回泛型类型。 Something is going to have to change. 某些事情将不得不改变。
You have a lot of work to do, so to repeat myself - treat this as a refactoring exercise and go step by step. 您有很多工作要做,所以重复我自己-将此视为重构练习,然后逐步进行。
myFragment
to be a A myFragment
and declare a type parameter <A extends DataTypaA
. myFragment
更改为A myFragment
并声明类型参数<A extends DataTypaA
。 See what needs to be done to get this to compile before moving on. data
to be SparseArray<B> data
. data
视为SparseArray<B> data
。 Presumably this needs to a SparseArray<T>
where T
is a DataTypeB
, or subtype thereof. SparseArray<T>
,其中T
是DataTypeB
或其子类型。 That means you are going to need a wildcard-based bound on B
. B
上基于通配符的绑定。 Something like B extends SparseArray<? extends DataTypeB>
B extends SparseArray<? extends DataTypeB>
这样的东西B extends SparseArray<? extends DataTypeB>
B extends SparseArray<? extends DataTypeB>
items
. items
。 You know that it is returned from your new generic type variable A extends DataTypeA
, so DataTypeA
needs to be generic and have a generic type variable returned from getData
. A extends DataTypeA
,因此DataTypeA
需要是通用的,并且具有从getData
返回的通用类型变量。 Let's say it is declared as DataTypeA<T extends DataTypeC>
with public T getData() { ... }
. public T getData() { ... }
声明为DataTypeA<T extends DataTypeC>
。 So now your type parameter sections change to: 因此,现在您的类型参数部分更改为:
class DataTypaA<T extends DataTypeC>
...
class myAdapter <A extends DataTypaA<C>,
B extends SparseArray<? extends DataTypeB>,
C extends DataTypeC>
extends FragmentStatePagerAdapter {
A myFragment;
SparseArray<B> data;
C items;
...
It's hard to go too far with this given the code you have posted - not all the classes and information is there, but this is the process you will have to follow. 鉴于您已发布的代码,对此很难走得太远-并非所有的类和信息都在那儿,但这是您必须遵循的过程。
For instance: you may not need to restrict C
to DataTypeC
. 例如:您可能不需要将
C
限制为DataTypeC
。 This then changes the type parameter sections on myAdapter
and DataTypeA
. 然后,这将更改
myAdapter
和DataTypeA
上的类型参数部分。 My assumption about SparseArray<B>
may also be incorrect - but your code doesn't compile at the moment so I can't tell. 我对
SparseArray<B>
假设也可能不正确-但您的代码目前无法编译,因此我无法告知。 A final implementation may go something like: 最终的实现可能类似于:
class myAdapter <A extends DataTypaA<C>,
B extends SparseArray<? extends DataTypeB,
? extends DataTypeC>,
C extends DataTypeC>
extends FragmentStatePagerAdapter {
A myFragment;
SparseArray<B, C> data;
C items;
public myAdapter(FragmentManager fm, A fragment) {
data = new SparseArray<B, C>();
myFragment = fragment;
items = myFragment.getData();
}
public B getItem(int position) {
return data.get(position);
}
@Override
public int getCount() {
return items.getList().size();
}
public void setData () {
items = myFragment.getItems (); //getItems return DataTypeC
data.setTheData(items);
}
}
For this I used the fake classes: 为此,我使用了伪类:
class DataTypaA<T extends DataTypeC> {
public T getData() { return null; }
public T getItems() { return null; }
}
class SparseArray<T, S> {
public T get(int foo) { return null; }
public void setTheData(S items){}
}
class DataTypeB {
}
class DataTypeC {
// do NOT use the raw type List - just done to get your code to compile
public List getList() { return null; }
}
abstract class FragmentStatePagerAdapter {
public abstract int getCount();
}
class FragmentManager {
}
When "genericizing" classes, you should replace all instances of genericized types by their generic: DataTypaA
becomes A
, etc. 当“泛化”类时,应将泛化类型的所有实例替换为其泛型:
DataTypaA
变为A
, DataTypaA
。
You also need to make sure return types from methods you call on other objects (like fragment.getData()
) are compatible with the generic. 您还需要确保您在其他对象(例如
fragment.getData()
)上调用的方法的返回类型与泛型兼容。 For that you can indicate the generic type extends a known class: 为此,您可以指示泛型扩展了一个已知的类:
public class MyAdapter<A extends MyData,B extends MyData,...>
The Java Tutorial on generics is good for more information. 有关泛型的Java教程可提供更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.