[英]Convert custom adapter to use generics in Java
我的Android应用程序中有一个适配器,我想使其通用。
适配器基本上是这样的:
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)
}
}
我将其更改为通用
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)
}
}
但是我遇到了不同的错误,当方法应该获取DataTypeC
参数并向其传递参数类型C
( data.setTheData (items)
),而该参数类型实际上是DataTypeC
,编译器建议将C
转换为DataTypeC
。 在getCount()
我也有错误建议将items
转换为DataTypeC
。
例如,当我尝试覆盖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);
}
任何想法如何解决它,使其成为100%通用的?
添加 :在您回答之后,我将其更改为支持通用类型的返回:
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
}
}
我遇到了编译错误……当我运行它时, <T>
和<C>
当然是同一类型。
第一个问题是您的非通用代码无法编译。 您有一个字段DataTypeB data;
然后将其分配给SparseArray<DataTypeB>
。 另外, setData
根本不编译。
忽略此...您已经声明了类型参数A, B, C
并更改了实例字段类型,但是您仍然尝试将DataTypaA
分配给DataTypaA
中的A myFragment
,并将SparseArray<DataTypeB>
分配给B data
。 当您将代码迁移到泛型时,您需要像重构那样进行处理-一次仅一步。
例如,通过现在进入,可以查看items = (C)myFragment.getData()
。 由于fragment
仍然是DataTypaA
类型, DataTypaA
大概它的getData()
方法不会返回泛型类型。 某些事情将不得不改变。
您有很多工作要做,所以重复我自己-将此视为重构练习,然后逐步进行。
myFragment
更改为A myFragment
并声明类型参数<A extends DataTypaA
。 在继续之前,请查看需要做什么才能使其编译。 data
视为SparseArray<B> data
。 大概这需要SparseArray<T>
,其中T
是DataTypeB
或其子类型。 这意味着您将需要在B
上基于通配符的绑定。 像B extends SparseArray<? extends DataTypeB>
这样的东西B extends SparseArray<? extends DataTypeB>
B extends SparseArray<? extends DataTypeB>
items
。 您知道它是从新的通用类型变量A extends DataTypeA
,因此DataTypeA
需要是通用的,并且具有从getData
返回的通用类型变量。 假设它是使用public T getData() { ... }
声明为DataTypeA<T extends DataTypeC>
。 因此,现在您的类型参数部分更改为:
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;
...
鉴于您已发布的代码,对此很难走得太远-并非所有的类和信息都在那儿,但这是您必须遵循的过程。
例如:您可能不需要将C
限制为DataTypeC
。 然后,这将更改myAdapter
和DataTypeA
上的类型参数部分。 我对SparseArray<B>
假设也可能不正确-但您的代码目前无法编译,因此我无法告知。 最终的实现可能类似于:
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);
}
}
为此,我使用了伪类:
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 {
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.