GithubHelp home page GithubHelp logo

drakeet / multitype Goto Github PK

View Code? Open in Web Editor NEW
5.7K 123.0 748.0 8.42 MB

Flexible multiple types for Android RecyclerView.

License: Apache License 2.0

Kotlin 100.00%
android-library recyclerview multitype recyclerview-multi-type one-to-many one2many

multitype's Introduction

MultiType

Easier and more flexible to create multiple types for Android RecyclerView.

Build Status License maven-central jetbrains-plugin

Previously, when we need to develop a complex RecyclerView / ListView, it is difficult and troublesome work. We should override the getItemViewType() of RecyclerView.Adapter , add some types, and create some ViewHolders relating to those types. Once we need to add a new item type, we have to go to the original adapter file and modify some old codes carefully, and these adapter classes will get more complicated.

Nowadays, I created a new intuitive and flexible way to easily create complex RecyclerViews, with the MultiType library, we could insert a new item type without changing any old adapter codes and make them more readable.

Getting started

In your build.gradle:

MultiType has been rebuilt based on AndroidX. If you are still using the android support library, please use me.drakeet.multitype:multitype:3.4.4 and me.drakeet.multitype:multitype-kotlin:3.4.4.

In addition, since 4.0.0 we have migrated to fully build with Kotlin. If you don't want to use Kotlin, you can use the last stable version me.drakeet.multitype:multitype:3.5.0 and see 3.x.

dependencies {
  implementation 'com.drakeet.multitype:multitype:4.3.0'
}

Usage

Step 1. Create a Kotlin class or data class, for example:

data class Foo(
  val value: String
)

Step 2. Create a class extends ItemViewDelegate<T, VH : ViewHolder>, for example:

class FooViewDelegate: ItemViewDelegate<Foo, FooViewDelegate.ViewHolder>() {

  override fun onCreateViewHolder(context: Context, parent: ViewGroup): ViewHolder {
    // If you want a LayoutInflater parameter instead of a Context,
    // you can use ItemViewBinder as the parent of this class.
    return ViewHolder(FooView(context))
  }

  override fun onBindViewHolder(holder: ViewHolder, item: Foo) {
    holder.fooView.text = item.value

    Log.d("ItemViewDelegate API", "position: ${holder.bindingAdapterPosition}")
    Log.d("ItemViewDelegate API", "items: $adapterItems")
    Log.d("ItemViewDelegate API", "adapter: $adapter")
    Log.d("More", "Context: ${holder.itemView.context}")
  }

  class ViewHolder(itemView : View): RecyclerView.ViewHolder(itemView) {
    val fooView: TextView = itemView.findViewById(R.id.foo)
  }
}
Or if you are using a custom View instead of XML layout, you can use ViewDelegate:

The ViewDelegate is a simple ItemViewDelegate that does not require to declare and provide a RecyclerView.ViewHolder.

class FooViewDelegate : ViewDelegate<Foo, FooView>() {

  override fun onCreateView(context: Context): FooView {
    return FooView(context).apply { layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT) }
  }

  override fun onBindView(view: FooView, item: Foo) {
    view.imageView.setImageResource(item.imageResId)
    view.textView.text = item.text

    view.textView.text = """
      |${item.text}
      |viewHolder: ${view.holder}
      |layoutPosition: ${view.layoutPosition}
      |absoluteAdapterPosition: ${view.absoluteAdapterPosition}
      |bindingAdapterPosition: ${view.bindingAdapterPosition}
    """.trimMargin()
  }
}

(See RichViewDelegate & RichView examples for more details)

Step 3. register your types and setup your RecyclerView, for example:

class SampleActivity : AppCompatActivity() {

  private val adapter = MultiTypeAdapter()
  private val items = ArrayList<Any>()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_list)
    val recyclerView = findViewById<RecyclerView>(R.id.list)

    adapter.register(TextItemViewDelegate())
    adapter.register(ImageItemViewDelegate())
    adapter.register(RichItemViewDelegate())
    recyclerView.adapter = adapter

    val textItem = TextItem("world")
    val imageItem = ImageItem(R.mipmap.ic_launcher)
    val richItem = RichItem("小艾大人赛高", R.drawable.img_11)

    for (i in 0..19) {
      items.add(textItem)
      items.add(imageItem)
      items.add(richItem)
    }
    adapter.items = items
    adapter.notifyDataSetChanged()
  }
}

That's all, you're good to go!

Advanced usage

One to many:

adapter.register(Data::class).to(
  DataType1ViewDelegate(),
  DataType2ViewDelegate()
).withKotlinClassLinker { _, data ->
  when (data.type) {
    Data.TYPE_2 -> DataType2ViewDelegate::class
    else -> DataType1ViewDelegate::class
  }
}

See OneDataToManyActivity, OneToManyFlow and OneToManyEndpoint for more details.

More methods that you can override from ItemViewDelegate:

open fun onBindViewHolder(holder: VH, item: T, payloads: List<Any>)
open fun getItemId(item: T): Long
open fun onViewRecycled(holder: VH)
open fun onFailedToRecycleView(holder: VH): Boolean
open fun onViewAttachedToWindow(holder: VH)
open fun onViewDetachedFromWindow(holder: VH)

Android Studio Plugin

An intellij idea plugin for Android to generate MultiType Item and ItemViewDelegate easily.

Screenshots

Pages created with MultiType:

License

Copyright (c) 2016-present. Drakeet Xu

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

multitype's People

Contributors

drakeet avatar feicien avatar geek5nan avatar hamberluo avatar kxfeng avatar litangyu avatar shawnlinboy avatar yeungkc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multitype's Issues

getPosition() 方法不能获得正确的 Position

Q: 如何在 ItemViewProvider 中获取到 item position? A: 从 v2.3.0 版本开始,只需要在你的 ItemViewProvider 子类里调用 getPosition() 方法即可。如果低于 v2.3.0 版本,可以调用 holder.getAdapterPosition() 获得同样结果。
在我使用 v2.3.4 时发现,他们俩并不一致
onClick: ===AdapterPosition:0===Position:1
onClick: ===AdapterPosition:1===Position:1
onClick: ===AdapterPosition:2===Position:2
onClick: ===AdapterPosition:3===Position:3
onClick: ===AdapterPosition:4===Position:4
onClick: ===AdapterPosition:5===Position:5
onClick: ===AdapterPosition:0===Position:0
onClick: ===AdapterPosition:1===Position:0
onClick: ===AdapterPosition:2===Position:0
onClick: ===AdapterPosition:2===Position:0
onClick: ===AdapterPosition:3===Position:3
onClick: ===AdapterPosition:3===Position:3
onClick: ===AdapterPosition:21===Position:22
onClick: ===AdapterPosition:22===Position:22
onClick: ===AdapterPosition:22===Position:22
onClick: ===AdapterPosition:23===Position:24
onClick: ===AdapterPosition:23===Position:24
这是我随手打印的日志

添加依赖运行项目后报错

你好,我按照步骤在build.gradle文件添加依赖运行项目报错,
# Error:Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Landroid/support/v4/app/ActionBarDrawerToggleHoneycomb$SetIndicatorInfo;

请问这个问题怎么解决?

看了代码,作者类库实现的想法不错,我提供一点我自己的想法吧

看了代码,实现的想法不错,
根据数据类型创建对应的ItemViewProviderd,ItemViewProviderd对ViewHolder执行了onCreateView,onBindView,这使得ViewHolder从Adapter抽离出来给多种Adapter复用.

不过感觉框架使用时代码还是比较多,
我说点自己的想法吧。

定义一个ItemViewProvider工厂接口,根据数据类型创建对应的ItemViewProvider,
代替之前的ItemTypePool.register.因为ItemTypePool.register是全局注册的,而ItemViewProviderFactory可以是使用时切换,也可以复用。

 public interface ItemViewProviderFactory {
         ItemViewProvider made(Object data);
  }

TypeItemsAdapter构
定义一个ItemViewProvider工厂接口,根据数据类型创建对应的ItemViewProvider,
代替之前的ItemTypePool.register.因为ItemTypePool.register是全局注册的,而ItemViewProviderFactory可以是使用时切换,也可以复用。

 public interface ItemViewProviderFactory {
         ItemViewProvider made(Object data);
  }

TypeItemsAdapter构造函数:datas 数据列表,使用者自己实现的ChatItemViewProviderFactory的ItemViewProvider工厂.

recyclerView.setAdapter(new TypeItemsAdapter(datas, new ChatItemViewProviderFactory()));

关于 二级 ViewProvider 示例疑问

你好,我在使用 版本号为 2.4.1 过程中,遇到一个问题,想请教下。

使用场景:
对于聊天消息,每种消息都有左右样式,但左右样式的数据绑定操作是一样,因此想说继承
ItemViewProvider ,重写 onCreateViewHolder() 方法,然后在这里根据数据对象的类型(发送或接受消息)来加载左或右布局,onBindViewHolder() 方法则进行相同的数据绑定操作。

问题:
在 onCreateViewHolder() 方法获取不到当前位置对应的数据对象,无法进行判断

其他:
1.看了 TimeMachine 的消息列表实现,看到左右消息区分了不同的 Content ,Provider ,但是数据内容,数据绑定是一样,这样实现会不会冗余?

2.在 "https://gank.io/post/5823bcf6421aa90e799ec2ad" 中,看到这句"每一种消息都有左边和右边的样式,分别对应别人发来的消息和你发出的消息。如果左边算一种,右边又算一种,就是比较不好的设计了,会导致布局内容重复、冗余,修改操作都要做两遍。最好的方案是让他们视被为同一种类型,然后在 item 框层次进行左右边判断和框架相关数据绑定。"
这里的 item 框层次进行左右判断,是指?

可能是哪里愚钝,没有理解,希望指点,谢谢~~

assertAllRegistered() 调用过时方法

由于 onFlattenClass(Object item) 方法过时,于是实现了MultiTypeAdapter.setFlatTypeAdapterMultiTypeAdapter() 方法,在程序运行时 crash 掉了,日志显示 assertAllRegistered() 方法下 adapter.indexOf(adapter.onFlattenClass(item)); 出错,因为onFlattenClass(item) 过时,未实现。
望改善,祝好!

how to register event like click or longclick

recyclerView's click event usually give a interface for you to register in activity, but i found in this library all adapter extends from MultiTypeAdapter class, I can't find any way to get this interface.

for example : if i left a interface setonTextClickListener in TextItemViewProvider , how can i register it in activity or is there any better way to do this?

关于全局类型池的疑问

根据我的理解

  1. 首先是在 Application 中,把一些全局的类型注册到了一个全局的 MultiTypePool 中
  2. 然后在具体使用的时候通过 applyGlobalMultiTypePool() 遍历注册到局部的 MultiTypePool 中
  3. 注册的本质,实际上是使 model 和 item 类型建立一种联系,使得可以在绑定数据的时候,通过 model 可以匹配到对应的 item

不知道这样理解对不对

所以我有些疑问

  1. 局部中注册的时候是否是把所有全局中的类型全部注册到了局部中(虽然会有覆盖)?那么如果我只是想使用全局中的部分类型,那么没用到的会不会造成浪费的情况

谢谢🙏😄

我遇到一个问题

FATAL EXCEPTION: main
Process: com.yunuo.ww, PID: 20664
java.lang.IndexOutOfBoundsException: Invalid index 4, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.yunuo.im.ui.activity.GroupProfileActivity$2.getSpanSize(GroupProfileActivity.java:120)
at android.support.v7.widget.GridLayoutManager.getSpanSize(GridLayoutManager.java:475)
at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:518)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:574)
at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3028)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2906)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3283)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15748)
at android.view.ViewGroup.layout(ViewGroup.java:4970)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2124)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1876)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1080)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5877)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5475)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:948)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:743)。
而我的报错地方代码如下:
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@OverRide
public int getSpanSize(int position) {
Item item = items.get(position);
return (items.get(position) instanceof SendMessage
|| items.get(position) instanceof Spilt
|| items.get(position) instanceof GroupMessage
|| items.get(position) instanceof GroupTitle
|| items.get(position) instanceof GroupMute) ? SPAN_COUNT : 1;
}
});
其中SPAN是4;但是出现数组越界,我下面布局有些是重复利用的,这种现象怎么解决??

一点小想法

这两天看auto-value,他的一个特别好的地方是Extension API,这样就可以自己扩展类似于auto-value-gson,auto-value-parcel这样的功能了,如果MultiType也能做类似的支持,是不是能在保证纯粹性和灵活性的基础上避免一些重复造轮子的事呢?

Why we need static and single TypePool?

Q: 为什么使用静态或者全局类型池?(Why we need static and single TypePool?)

A: 我不反对局部或临时类型池的设计,你可以 fork 这个项目自行实现,它们对于内存更加友好(但也只是微小优势而已),但在我看来,全局类型池在多方面更好:

  • 它能够显式连接 Type 和它的 Item View,能够在同一地方统一 register,这将避免分散,带来很好的直观性和可管理性;
  • 一个应用不会有超级大量的类型定义,类型 class 和 provider 对象都是非常轻薄的对象,直接静态存于内存,并不会导致内存泄漏和大的内存占用问题,几乎可以忽略;
  • 至于要不要支持 optional 的局部类型池参数,我也是不喜欢支持的,前面说了,这是没必要的,而且若是可选(optional)也会使用户疑惑:“到底要还是不要?”

因此我喜欢和坚持使用全局静态类型池,它不会带来什么问题,而且好处诸多,有人给我提交了使用反射的方法来自动获取类型连接,为了避免性能话题,我不喜欢反射,而且将类型连接变得复杂和不可见性未必是好事。我一直坚持的原则是:写简单的代码,写可读的代码,实现复杂的需求(你们看我的代码是不是感觉很自然而然而且可读性十分好?)

Performance testing for global static MultiTypePool

I found a Xiaomi 2s (Android 5.1.1) mobile phone for testing the performance of global static MultiTypePool today. I registered 9999 ItemContent classes & ItemViewProvider instances in the Application beginning. The ItemContent contains 12 random Strings and the ItemViewProvider.TestViewHolder contains 12 TextView, and I put my target type after 10000 index for test Adapter onCreateViewHolder's performance.

The results of this testing showed that:

image

The initialization of registering 10000 types just spend 10ms! And the memory usage is also very low because ItemViewProvider instances do not hold any other class instance actually. And the RecyclerView which contains MultiType also perform perfectly and smoothly.

So, is there a application reach 10000 types? Do we really need a local type pool? The answer is obvious.

Chinese translated version:

找了一个小米 2s 来对 MultiType 进行测试,注入 9999 个 ItemContent class 和 ItemViewProvider 对象,ItemContent 包含 12 个随机 String,ItemViewProvider.TestViewHolder 包含 12 个 TextView 对象,并将我们使用的 Type 排到第 10000 位以后(检索严格模式)。

测试结果表明,性能极好。初始化注册 10000 个类型,只要 10 毫秒左右!而且内存占用也极低,因为类型 class 和 provider 对象都是非常非常轻薄的对象,后者虽然是以传统实例注册(其实 class 也是实例),但 provider 层面不持有任何对象,它只提供生产方法;另外,尽管 target index 在 10000 位以后,但丝毫不会影响列表滑动流畅性,因为计算个 10000 次,对于我们的手机 CPU,简直比我们人类 1 + 1 还简单的事情。这更近坚定了我使用全局类型池的设计。

那么问题来了,即使是淘宝,有超过 10000 个 item types 吗?我们真的需要局部类型池吗?答案我想是显然的。

TypeItem 的作用?

hi @drakeet 我想问一下TypeItem的作用是什么,为什么不直接使用ItemContent而是还要再包装一层,还有extra这个字段的意义是什么呢? 是在onBindViewHolder的时候用于区分?谢谢

message

thanks you library.

When I met a different view of an entity when , how can I do ?

itemProvider中绑定数据的疑问

itemProvider中,onBindViewHolder中提供了当前viewholder和相关的数据类,但是我想访问上一个位置的数据,应该如何做? 问题抽象一下,就是当前item的不仅和自身状态有关,也和上一个item的数据有联系。

Crash if app reactive from background

when press back key, and then restart app, it will crash.

Process: me.drakeet.multitype.sample, PID: 25781
java.lang.RuntimeException: Unable to start activity ComponentInfo{me.drakeet.multitype.sample/me.drakeet.multitype.sample.page.MainActivity}: java.lang.IllegalArgumentException: You have registered the TextItemContent type. It should not be added again.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2359)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2422)
at android.app.ActivityThread.access$800(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1319)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5313)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1116)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:809)
Caused by: java.lang.IllegalArgumentException: You have registered the TextItemContent type. It should not be added again.
at me.drakeet.multitype.ItemTypePool.register(ItemTypePool.java:38)
at me.drakeet.multitype.sample.page.MainActivity.onCreate(MainActivity.java:65)
at android.app.Activity.performCreate(Activity.java:6036)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2422) 
at android.app.ActivityThread.access$800(ActivityThread.java:159) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1319) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5313) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1116) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:809) 

请问异步数据如何控制位置?

你好,drakeet。
我的数据是网络获取的,在一个接口获取第一个数据之后 items.add() ,
在另一个接口获取第二个数据后也 items.add(),而网络请求是异步的,
这时会出现这两个数据在界面上显示位置错乱,在不考虑网络请求嵌套的情况下,
有没有什么好的解决办法。
我现在是这样做的,网络请求之前,先 items.add(index,data) 这两个类型数据的默认值来占位,
请求成功后先 items.remove(index) 再 items.add(index, data),请求失败后 直接items.remove(index),
但是这样又会带来其他的问题。
请问你有什么好的解决方案吗?

Performance Issues

  • when I use this library in my app, the layout like this picture. as you see, this layout contain at least one TitleItem and GridRecyclerViewItem, sometimes the Grid has a large number over 1000
  • During test, first time I init data to layout, i call the notifydatasetchanged(), it has a verbose
    ``Skipped 72 frames! The application may be doing too much work on its main thread`. I think this problem is caused by GridRecyclerViewItem, MultiTypeAdapter needs to maintance serveal adapter, first time refresh will casue this problem.
  • same layout use one normal RecyclerView with GridLayoutManager and setSpanSizeLookup will not cause this problem. If I use MultiTypePool.getProviderByIndex to achieve the same function, I think there is no different with normal Adapter, do you hava any plan about this problem?

image

提个建议

很好的设计,感谢分享!建议在onBindViewHolder的方法里加上position这个参数吧

RecyclerView 嵌套水平 RecyclerView 发现的一个 bug

drakeet 你好:
sample 中提供的 BilibiliActivity ,无意中我发现了一个 bug。

     for (int i = 0; i < 10; i++) {
            items.add(data.category0);
            items.add(data.postArray[0]);
            items.add(data.postArray[1]);
            items.add(data.postArray[2]);
            items.add(data.postArray[3]);
            
            items.add(data.postArray[0]);
            items.add(data.postArray[1]);

            items.add(new PostList(data.postList));
    }

我在构造数据的地方多添加了 2 条数据,这时 RecyclerView 就会向下移动,而不是从第一条数据开始显示。

期待的效果如下图:

1

而实际的情况如下图:

2

我怀疑是水平 RecyclerView 抢占焦点导致的问题,如果你有时间的话,也可以确认一下。

MultiType 3.0

  • Support one type to different(many) ItemViewBinders in one RecyclerView
  • Rename the ItemViewProvider to ItemViewBinder(done in v2.5.0)
  • Remove all the @Deprecated classes/methods
  • Remove the golbal type pool GlobalMultiTypePool
  • Retrofit the constructors of MultiTypeAdapter
  • Fix some unchecked
  • Rename TypePool#getContents() to getClasses() (#109)

  • Update and supply full docs

有个item包含的是gridview样式 我要分别点击执行不同的时间逻辑 怎么搞

有个item包含的是gridview样式 我要分别点击gridview中的item执行不同的事件逻辑 怎么搞 ??
除了extends MultyTypeAdapter 加个setOnItemClickListener方法可以实现之外 还有其他更好的方式吗
一般的事件都是可以在ItemViewProvider中实现
qq 20161203100834
但是如果像gridview这种我要分别点击执行不同的时间逻辑还有更好的方法么?image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.