我正在尝试为RecyclerView实现自定义适配器,而不使用单个强制转换或实例。
我的实施受this article的启发。
我的适配器应该能够显示以下类型的任何项目:
public interface InboxVisitable {
int getType(InboxTypeFactory inboxTypeFactory);
}
我有2种此类型的实现:
public class InboxMonthViewModel implements SentInboxFragment.InboxVisitable {
public String month;
@Override
public int getType(SentInboxFragment.InboxTypeFactory inboxTypeFactory) {
return inboxTypeFactory.getType(this);
}
}
public class InboxMessageViewModel implements SentInboxFragment.InboxVisitable {
public String message;
@Override
public int getType(SentInboxFragment.InboxTypeFactory inboxTypeFactory) {
return inboxTypeFactory.getType(this);
}
}
InboxFactoryType是一个工厂,用于将特定类型链接到适配器用于确定视图类型的唯一ID:
public static class InboxTypeFactory {
public int getType(InboxMessageViewModel message) {
return R.layout.cell_inbox_message;
}
public int getType(InboxMonthViewModel month) {
return R.layout.cell_inbox_message;
}
public InboxViewHolder getViewHolderForType(View itemView, int viewType) {
if (viewType == R.layout.cell_inbox_message) {
return new InboxMessageViewHolder(itemView);
} else {
return new InboxMonthViewHolder(itemView);
}
}
}
如您所见,工厂还负责为每种可能的类型创建视图持有者。
View Holder是一个通用视图持有者,因为适配器只需要知道一种类型的持有者:
private static abstract class InboxViewHolder<T extends InboxVisitable> extends RecyclerView.ViewHolder {
public InboxViewHolder(View itemView) {
super(itemView);
}
public abstract void bind(T data);
}
而且,由于我有两种类型的数据,我有2个相应的视图持有者:
private static class InboxMessageViewHolder extends InboxViewHolder<InboxMessageViewModel> {
public InboxMessageViewHolder(View itemView) {
super(itemView);
}
@Override
public void bind(InboxMessageViewModel data) {
// do stuff
data.message;
}
}
private static class InboxMonthViewHolder extends InboxViewHolder<InboxMonthViewModel> {
public InboxMonthViewHolder(View itemView) {
super(itemView);
}
@Override
public void bind(InboxMonthViewModel data) {
// do stuff
data.month;
}
}
现在,对于有趣的部分,适配器。
他正在使用工厂为每种特定数据类型获取正确的视图类型,并且通过该工厂,他还将为每个数据创建视图持有者。
适配器正在保存他正在操作的最通用类型的数据列表:InboxVisitable
。
private static class InboxAdapter extends RecyclerView.Adapter<InboxViewHolder> {
private final InboxTypeFactory inboxTypeFactory;
List<InboxVisitable> itemList;
InboxAdapter() {
inboxTypeFactory = new InboxTypeFactory();
}
@Override
public InboxViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View itemView = LayoutInflater.from(parent.getContext())
.inflate(viewType, parent, false);
return inboxTypeFactory.getViewHolderForType(itemView, viewType);
}
@Override
public void onBindViewHolder(InboxViewHolder holder, int position) {
//noinspection unchecked
holder.bind(itemList.get(position));
}
@Override
public int getItemCount() {
return itemList.size();
}
}
这段代码完美无缺,但它有一个小缺陷:当绑定视图持有者时,编译器告诉我,当我向InboxVisitable
方法bind(T)
提供RecyclerView.Adapter<InboxViewHolder<? extends InboxVisitable>>
时,会有一个未经检查的强制转换。
我尝试添加以指定adaper bind()
(并在任何地方反映规范)但是,? extends InboxVisitable
期望InboxVisitable
,但我只提供给他一个bind()
。
我如何处理所有这些通用的疯狂,没有强制转换,没有实例,也没有对此library(shiny)
myModUI <- function(id) {
ns <- NS(id)
tagList(
fluidRow(
splitLayout(cellWidths=c("75%","25%"),
plotOutput(ns("g")),
radioButtons(ns("radio"),label = "buttons",
choices = list("with intercept"=1,"without intersept"=2),
selected = 1))
)
)
}
myMod <- function(input, output, server, seed) {
output$g <- renderPlot({
set.seed(seed)
xx <- rnorm(10)
yy <- rnorm(10)
plot(xx,yy)
abline(reg=lm(yy~xx), col=2, lwd=ifelse(input$radio==1,2,1))
abline(reg=lm(yy~xx+0), col=3, lwd=ifelse(input$radio==2,2,1))
})
return(reactive(input$radio))
}
server <- shinyServer(function(input, output, server) {
lapply(1:5,function(i) {
callModule(myMod,i,seed=i)
})
})
ui <- shinyUI(fluidPage(
titlePanel("My loop test"),
mainPanel(
lapply(1:5,function(i) {
myModUI(i)
})
)
))
shinyApp(ui=ui,server=server)
方法进行未经检查的调用?
非常感谢, 皮尔