Giter Site home page Giter Site logo

nitrico / lastadapter Goto Github PK

View Code? Open in Web Editor NEW
776.0 20.0 70.0 225 KB

Don't write a RecyclerView adapter again. Not even a ViewHolder!

License: Apache License 2.0

Java 26.94% Kotlin 73.06%
recyclerview recyclerview-adapter databinding kotlin kotlin-android kotlin-library android android-library viewholder

lastadapter's Introduction

Download Android Arsenal License Gitter

LastAdapter

Don't write a RecyclerView adapter again. Not even a ViewHolder!

  • Based on Android Data Binding
  • Written in Kotlin
  • No need to write the adapter
  • No need to write the viewholders
  • No need to modify your model classes
  • No need to notify the adapter when data set changes
  • Supports multiple item view types
  • Optional Callbacks/Listeners
  • Very fast — no reflection
  • Super easy API
  • Tiny size: ~30 KB
  • Minimum Android SDK: 9

Setup

Gradle

// apply plugin: 'kotlin-kapt' // this line only for Kotlin projects

android {
    ...
    dataBinding.enabled true 
}

dependencies {
    compile 'com.github.nitrico.lastadapter:lastadapter:2.3.0'
    // kapt 'com.android.databinding:compiler:GRADLE_PLUGIN_VERSION' // this line only for Kotlin projects
}

Usage

Create your item layouts with <layout> as root:

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="item" type="com.github.nitrico.lastadapterproject.item.Header"/>
    </data>
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{item.text}"/>
        
</layout>

It is important for all the item types to have the same variable name, in this case "item". This name is passed to the adapter builder as BR.variableName, in this case BR.item:

// Java
new LastAdapter(listOfItems, BR.item)
           .map(Header.class, R.layout.item_header)
           .map(Point.class, R.layout.item_point)
           .into(recyclerView);
// Kotlin
LastAdapter(listOfItems, BR.item)
           .map<Header>(R.layout.item_header)
           .map<Point>(R.layout.item_point)
           .into(recyclerView)

The list of items can be an ObservableList if you want to get the adapter automatically updated when its content changes, or a simple List if you don't need to use this feature.

LayoutHandler

The LayoutHandler interface allows you to use different layouts based on more complex criteria. Its one single method receives the item and the position and returns the layout resource id.

// Java sample
new LastAdapter(listOfItems, BR.item)
           .handler(handler)
           .into(recyclerView);

private LayoutHandler handler = new LayoutHandler() {
    @Override public int getItemLayout(@NotNull Object item, int position) {
        if (item instanceof Header) {
            return (position == 0) ? R.layout.item_header_first : R.layout.item_header;
        } else {
            return R.layout.item_point;
        }
    }
};
// Kotlin sample
LastAdapter(listOfItems, BR.item).layout { item, position ->
    when (item) {
        is Header -> if (position == 0) R.layout.item_header_first else R.layout.item_header
        else -> R.layout.item_point 
    }
}.into(recyclerView)

For further information, please take a look at my article at Medium.

Custom fonts

You might also want to try FontBinder to easily use custom fonts in your XML layouts.

Acknowledgments

Thanks to Yigit Boyar and George Mount for this talk.

Author

Miguel Ángel Moreno

I'm open to new job positions - Contact me!

AngelList Email Facebook Google+ Linked.in Twitter

License

Copyright 2016 Miguel Ángel Moreno

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.

lastadapter's People

Contributors

nitrico 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

lastadapter's Issues

Option for manually binding custom variables

I'd like to able to bind presenter or other non-static handlers for views inside items:

  <variable
      name="presenter"
      type="com.example.module.somemodule.SomePresenter"/>

  <variable
      name="item"
      type="com.example.viewmodels.SomeViewModel"/>
</data>
...
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    onClick="@{presenter.doSmth(item)}"/>

Getting hold of a view holder would allow such thing. But I can only access it in Type<ItemBinding>.onClick():

Type<SomeBinding> someType = new Type<>(R.layout.some_item);
someType.onClick(new Function1<ViewHolder<SomeBinding>, Unit>() {
  @Override
  public Unit invoke(ViewHolder<SomeItemBinding> viewHolder) {
    viewHolder.getBinding().setVariable(BR.presenter, presenter); // I need this somewhere outside
    return Unit.INSTANCE;
  }
});

How to bind data for ImageView

Hello, I use
android:src="@{item.drawableRes}" for ImageView and it doesn't work.
Where drawableRes is an integer value of drawable resource (R.drawable.icon).

How to use more <data></data> and more BR ?

Hello nitrico, i am so glad to used your library, it's save my work time, but how can i use more LastAdapter ? Are each BR must be item variabel or must same name "BR.item" ?
Thanks before i hope you understand what i ask.

Get a ViewHolder object in the onBind() (ItemTouchHelper support)

I need to get a ViewHolder object in the onBind().

This is necessary for use functions of ItemTouchHelper, for example:

private val ITEM = Type<ItemButtonBinding>(R.layout.item)
            .onBind {
                binding.vButton.setOnTouchListener({ v, event ->
                    if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
                        touchHelper.startDrag(viewHolder)
                    }
                    false
                })
            }

API for LastAdapter 2.0

LastAdapter 2.0 is coming soon and I'd like to hear your thoughts or suggestions about its API.

Listeners:

  • They will be specific for each item type, instead of one for the whole adapter.
  • They probably will not provide parameters view, type and item anymore, only binding and position. item and view will be available through binding.item and binding.root.
  • I will add an onRecycle callback for the view being recycled.
  • Maybe another onCreate callback for the ViewHolder being created (for the first time). Not sure yet.
  • Should I keep the onClick and onLongClick listeners? Are you really using them? I mean, you can also set them in the layout itself or in the onBind callback.

The API for Kotlin is going to be pretty cool, in my opinion:

LastAdapter.with(Data.items, BR.item)
    .map<Header, ItemHeaderBinding>(R.layout.item_header) {
        onCreate { println("Created ${binding.item} at position $position") }
        onBind { println("Bound ${binding.item} at position $position") }
        onClick { context.toast("Click on ${binding.item} at position $position") }
        onLongClick { context.toast("Long click on ${binding.item} at position $position") }
        onRecycle { println("Recycled ${binding.item} at position $position") }
    }
    .map<Point, ItemPointBinding>(R.layout.item_point) /*{
        onCreate { println("Created ${binding.item} at position $position") }
        onBind { println("Bound ${binding.item} at position $position") }
        onClick { context.toast("Click on ${binding.item} at position $position") }
        onLongClick { context.toast("Long click on ${binding.item} at position $position") }
        onRecycle { println("Recycled ${binding.item} at position $position") }
    }*/
    .into(list)

API for Java is not so cool, at least right now...

LayoutHandler / TypeHandler:
With the listeners being specific for each type, the "LayoutHandler" should become a "TypeHandler" and returns more than just the layout. Probably something like:

val typeHeader = Type<ItemHeaderBinding>(R.layout.item_header)
    .onBind { println("Bound ${binding.item} at position $position") }
    .onClick { context.toast("Click on ${binding.item} at position $position") }
    .onLongClick { context.toast("Long click on ${binding.item} at position $position") }
    .onRecycle { println("Recycled ${binding.item} at position $position") }

val typePoint = Type<ItemPointBinding>(R.layout.item_point)
    .onClick { context.toast("Click on ${binding.item} at position $position") }

val typeHeaderFist = Type<ItemHeaderFirstBinding>(R.layout.item_header_first) 
    .onBind { println("Bound ${binding.item} at position $position") }

LastAdapter.with(Data.items, BR.item) {
    when (item) {
        is Header -> if (position == 0) typeHeaderFirst else typeHeader
        is Point -> typePoint
        else -> null
    }
}.into(list)

Data Binding:
I'm even considering the possibility of letting the "users" decide if they want to use Data Binding or not, and do the binding manually if they want.

Feel free to leave your thoughts here :)

payload binding

Is possibile to handle the update of only some item attributes and not entire item???

Crash after migration to 2.2.2

LastAdapter 2.2.2
Kotlin 1.1.2-3
Start experienced one more crash today with following stacktrace

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.support.v7.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference
                                         at android.support.v7.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:3610)
                                         at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3323)
                                         at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1637)
                                         at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:343)
                                         at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
                                         at android.view.Choreographer.doCallbacks(Choreographer.java:686)
                                         at android.view.Choreographer.doFrame(Choreographer.java:618)
                                         at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
                                         at android.os.Handler.handleCallback(Handler.java:751)
                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                         at android.os.Looper.loop(Looper.java:154)
                                         at android.app.ActivityThread.main(ActivityThread.java:6121)
                                         at java.lang.reflect.Method.invoke(Native Method)
                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

Works stable after downgrade version to 2.0.0

DataBinderMapperImpl not generated

Hi, I am getting following error when I attempt to use the library in my project.

Library version 2.3.0
Android Studio: 3.1 Canary 8
Compile SDK 27
Gradle and KAPT version: 3.1.0-alpha08

:app:javaPreCompileDebug UP-TO-DATE C:\pahttoproject\app\build\generated\source\kapt\debug\android\databinding\DataBinderMapperImpl.java:7: error: cannot find symbol addMapper(new com.github.nitrico.lastadapter.DataBinderMapperImpl()); ^ symbol: class DataBinderMapperImpl location: package com.github.nitrico.lastadapter 1 error :app:compileDebugJavaWithJavac FAILED

Thank you :)

Changelog for version 2.3.0?

I see new version 2.3.0 but no change log there. We use LastAdapter in every project. It is important to know the changes before updating. Can you please provide the changes?

Thanks a lot for the wonderful library!

IndexOutOfBoundExeption when notifyDataSetChanged() is called

Stack trace:

07-10 15:11:53.936 E/AndroidRuntime: FATAL EXCEPTION: main
                                     Process: com.nejctomsic.registerzdravil.debug, PID: 18830
                                     java.lang.IndexOutOfBoundsException: Index: 3, Size: 1
                                         at java.util.ArrayList.get(ArrayList.java:411)
                                         at com.github.nitrico.lastadapter.LastAdapter.getType(LastAdapter.kt:178)
                                         at com.github.nitrico.lastadapter.LastAdapter.onViewRecycled(LastAdapter.kt:132)
                                         at com.github.nitrico.lastadapter.LastAdapter.onViewRecycled(LastAdapter.kt:27)
                                         at android.support.v7.widget.RecyclerView$Recycler.dispatchViewRecycled(RecyclerView.java:6064)

The issue was not present until version 2.2.2. It was added in this commit. The problem is when notifyDataSetChanged() is called on the adapter, with a new backing list that has fewer elements than the old one. To fix this, the line that compares the position should be reverted to this one.

Support auto-loading paginated data

We have many REST endpoints that return paginated data. This means we get eg 30 items from an API call, and need to load additional items from the server as the user scrolls. As far as I can see, this is not supported in LastAdapter.

I might be able to contribute this functionality. Do you think this makes sense in LastAdapter? And what should the API look like?

These are the necessary parameters for pagination:

  • page loader callback (takes page number, returns list of new items)
  • number of items remaining to auto-load (eg if this is set to 10, load when less than 10 items are remainig before the end of the list)
  • first page number (optional, can be 0 by default)
  • item count (optional, can be Integer.MAX_VALUE by default)

onBindListener overload for lambdas

Having to do this is ugly:

        LastAdapter.with(content, BR.item)
                .map<ListItem>(R.layout.fragment_grid_list_item)
                .onBindListener(object : LastAdapter.OnBindListener {
                    override fun onBind(item: Any, view: View, pos: Int) {
                        doStuff()
                    }
                })
                .into(contentView)

I would much rather do this:

        LastAdapter.with(content, BR.item)
                .map<ListItem>(R.layout.fragment_grid_list_item)
                .onBindListener { item, view, pos -> doStuff() }
                .into(contentView)

Also, similar for click and long click listeners.

I can provide the PR if you approve this feature request.

Huge method in Java project count due to kotlin

I love the idea of this library and I understand that it is very nice to develop it in Kotlin. However, due to the use of kotlin a dependency on the kotlin-stdlib is added which causes 5000 extra methods in the dex and unfurtunately that makes it impossible for me to use. Would be great to have a Java variant as well for those of us who are not joining the kotlin hype (yet)

Mixing version can lead to runtime crashes

`apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.fintech.assetvantage"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dataBinding{
enabled true
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
kapt 'com.android.databinding:compiler:3.0.0-beta6'
implementation 'com.github.nitrico.lastadapter:lastadapter:2.2.2'
}
`
My app:build.gradle file is like above.
support library dependacy gives error like Mixing version can lead to runtime crashes

How to Redraw/notifyDatachange when after property value change

Hi,

I have an ObservableArrayList of a simple Pojo Message

private final ObservableArrayList<Message> messageList = new ObservableArrayList<>();

new LastAdapter(messageList, BR.message)
                .map(Message.class, R.layout.item_message)
                .into(mRecycleView);

When the user clicks on an ImageView I wanna mark it as read and redraw this line/item. I have added an event handler for this.

<import type="..Handler" />

<variable
    name="message"
    type="....model.Message" />

<ImageView
    android:id="@+id/read"
    android:onClick="@{(view) -> Handler.markAsread(view, message)}"
    android:visibility="@{notificacao.lido ? View.GONE : View.VISIBLE}"
    ...
 />
public static class Handler {
    public static void markAsread(View view, Message message) {
        message.setRead(true);
    }
}

But I have no idea how to redraw this item on the RecyclerView. Just change the Message attribute seems does not work.

How to use payloads refresh single item special element ?

here is a item which include image and text

now, i want to use adapter notifyItemChanged(position, payload) method to just refresh the text not the image ,

but in the code,just holder.binding.executePendingBindings() still will refresh the image

so how to refresh item special element in databinding ?

Crash on LayoutHandler in kotlin

There is a problem with LayoutHandlerAdapter. I want to use it in my project, when LastAdapter with Layout is loader I've got KotlinNullPointerException. Here is my code:
LastAdapter(viewModel.conversation, BR.item).layout { item, _ -> when(item) { is ContactItem -> { if (item.isCustomer) { R.layout.item_client } else { R.layout.item_service } } else -> R.layout.item_service } }.into(claimContactRv)

When I use normal LastAdapter (without LayoutHandling) everything works well.

I also run example project and get the same error. I paste it below.

kotlin.KotlinNullPointerException at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:109) at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:27) at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6508) at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:125) at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:27) at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6541) at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5484) at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5750) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5589) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5585) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2231) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1558) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1518) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:610) at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3719) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3436) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3988) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1197) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1769) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1197) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) at android.widget.FrameLayout.onLayout(FrameLayout.java:273) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:443) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) at android.widget.FrameLayout.onLayout(FrameLayout.java:273) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) at android.widget.LinearLayout.onLayout(LinearLayout.java:1495) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) at android.widget.FrameLayout.onLayout(FrameLayout.java:273) at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2678) at android.view.View.layout(View.java:16630) at android.view.ViewGroup.layout(ViewGroup.java:5437) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2171) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1931) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) at android.view.Choreographer.doCallbacks(Choreographer.java:670) at android.view.Choreographer.doFrame(Choreographer.java:606)

Add missed Gradle wrapper

It looks like that files gradle-wrapper.jar and gradle-wrapper.properties were missed in this project, so it is impossible to build the project from CLI.

Could you please add them?

kapt databinding error

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:kaptGenerateStubsDebugKotlin'.

Allow more type specific reactions without switch statements

In my own use of data binding and view holders I have some more complex interactions from the view to the view holder. I have several controls within an item that have their own listeners. So I have different ViewHolder types and I actually have a variable in the layout for the holder and I can bind to or use methods on the ViewHolder to do listeners or provide additional data to the view.

Looking at this library as a possible alternative to my complex Adapter and ViewHolder, I don't see a good way to handle these more complex interactions. It is possible using the OnBindListener, but that is a single listener for all types. You end up having to do a switch statement and probably a cast. That is a code smell and what we would like to avoid by using a library like this.

I am trying to think what is the best way to accomplish this in a minimally invasive way. What I am envisioning is a version of the map call that also accepts a parameter of a class that extends LastAdapter.ViewHolder which has an onBind method that subclasses can override to do custom work (and FYI you should add support for unbinding as well to clean up things when a view is removed from the list).

Just sort of thinking out loud here.

bind ViewModel is better than bind Model

In MVVM design mode, it's bad to attach View and Model. So it's any way to bind ViewModel?
eg:
`

<data>
    <variable name="item" type="com.github.nitrico.lastadapterproject.item.Header"/>
</data>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@{item.text}"/>

`
there is bind a Model Header,it's possible to bing a ViewModel like HeaderViewModel?

How to add item

Hello miguel,
how i can add item when recyclerview has created ?

this mycode

private ObservableArrayList<ImageExpiredEntity> imageExpiredObservable = new ObservableArrayList<>();
imageExpiredAdapter = new LastAdapter(imageExpiredObservable, BR.imageExpired) .map(ImageExpiredEntity.class, typeImageExpired)(mRecyclerViewImageExpired);

this code how to add item on observable list

ImageExpiredEntity imageExpiredEntity = new ImageExpiredEntity(); imageExpiredEntity.setPath_file(bundle.getString("file_path")); imageExpiredEntity.setFile_name(bundle.getString("file_name"));
imageExpiredObservable.add(imageExpiredEntity);

thanks

Bind issues after Android Studio 3.2 release

I just migrated whole project to Android Studio 3.2.1, gradle 4.10, Kotlin 1.2.71

I can't build project due to error with generated binding class:

image

Do you have any idea what might be the cause? Cleaning project does not help here. I'm using databinding compiler from androidx reference, but i doubt that this have any impact on this

OnBind not working

I am using like this in my adapter but somehow the code in onBind does not execute

LastAdapter(doList(list), BR.item)
                .map<Header, EventHeaderBinding>(R.layout.event_header)
                .map<Item, ItemEventBinding>(R.layout.item_event) {
                    onBind {
                        Log.d("Bind","# ${it.adapterPosition}")
                        val position = it.adapterPosition - 1
                        if (position >= 0) {
                            if (list[position].from_date == list[position - 1].from_date) {
                                it.binding.date.visibility = View.INVISIBLE
                            } else {
                                it.binding.date.visibility = View.VISIBLE
                            }
                        } else {
                            it.binding.date.visibility = View.VISIBLE
                        }
                    }
                    onClick {
                        val intent = Intent(applicationContext, EventDetailActivity::class.java)
                        intent.putExtra(event_detail_bundle_name, it.binding.item)
                        startActivity(intent)
                    }
                }.into(event_recycler) 

Doesn't work with RecyclerView support lib version 25.0.0

The library doesn't work properly when I try to update the recyclerview-v7 dependency to version 25.0.0.

Some items are not bound correctly or not bound at all. I don't know if it is related to a modification introduced on purpose to the RecyclerView library or a bug.

Any help would be appreciated.

Support binding to LiveData (pass LifecycleOwner to items)

Since version 3.1 Android Studio supports databinding to LiveData. But in order to track changes of a LiveData field, ViewDataBinding object must be provided with LifecycleOwner which LastAdapter does not. So binding to LiveData via LastAdapter is efficiently onetime binding.
Please, add possibility to pass LifecycleOwner into LastAdapter (probably, constructor argument will do fine).

Error on BR

Hi, I'm trying to use LastAdapter, and have a problem. I refered app on github, and have error "Unresolved reference: BR". Is this error occur before?

Here's my item layout source

<layout xmlns:android="http://schemas.android.com/apk/res/android" >

<data>
    <variable name="item" type="com.example.icarusud.project.RecyclerViewItem" />
</data>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@{item.text}" />
</layout>

is it impossible to use object which extends RealmObject?

Hi :)
I'm using relam mobile database with lastadapter, and i caught RealmProxyError when i put ArrayList contains object extending RealmObject.
Is it impossible to use object which extends RealmObject?

// class Restaurant is extending RealmObject

ArrayList<Restaurant> arrayListForListView = new ArrayList<>();
realm = Realm.getDefaultInstance();
realm.beginTransaction();
RealmList<Restaurant> restaurants = realm.where(History.class).findAll().get(0).getHistoryList();
arrayListForListView.addAll(restaurants);        
new LastAdapter(arrayListForListView, BR.content)
                .map(Restaurant.class, new ItemType<HistoryItemBinding>(R.layout.history_item) {
                    @Override
                    public void onBind(Holder<HistoryItemBinding> holder) {
                        super.onBind(holder);
                        holder.getBinding().setPosition(holder.getLayoutPosition());
                        holder.getBinding().setActivity(HistoryItemActivity.this);
                    }
                })
                .into(binding.recyclerView);

Use DiffUtil to update list content

Hey there, really awesome little library 👍

The RecyclerView support library includes a tool to calculate the difference between two lists and update the adapter's content with more precision. It's called DiffUtil.

Dou you think it would be feasible to include this functionality in this library by providing a seperate method next to notifyDataSetChanged() and all the others, that uses this utility?

I am willing to invest some time into implementing this if you are interested.

Sorry I just saw this was already asked a while ago in #30.
I think this is basic stuff that should be included in every RecyclerView adapter. I guess I could just implement it in my own code, but getting it for free through this library would be even better.

Change layout by condition

Is possible to I access my layout to change the text color like

if(item.price > 100) {
// change my TextViewColor
}

instead of use LayoutHandler with 2 differents layout:

LastAdapter(items, BR.something)
                .layout { item, position ->
                    if (items[position].price > 100) {
                        R.layout.item_red
                    } else {
                        R.layout.item_green
                    }
                }.into(something)

First Item of recyclerview not clickable

All the item are displayed on the screen perfectly but first item (Item1) is not clicked.
Other items are clicked perfectly fine.
My code is like this:
MyActivity

private val mainList = listOf<String>("Item1", "Item2", "Item3")

LastAdapter(mainList, BR.item)
                .map<String, ItemMainListBinding>(R.layout.item_main_list) {
                    onBind {
                        onClick {
                            toast(it.binding.item.toString())
                        }
                    }
                }
                .into(mBinding.rcvMain)

item_main_list.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="item"
            type="String" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:foreground="?attr/selectableItemBackground"
        android:orientation="vertical">

        <TextView
            android:id="@+id/text_list_item"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="8dp"
            android:paddingEnd="16dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:paddingStart="16dp"
            android:paddingTop="8dp"
            android:text="@{item}"
            android:textColor="@android:color/black"
            android:textSize="22sp"
            tools:text="Item Name" />
    </LinearLayout>
</layout>

Diff Utils usage

It would be really amazing if DiffUtils can be plugged in with this library. Are you planning on doing it?

How can one set OnChildClickListener for item

is it possible to add image in imageview via picasso

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@{viewmodel.firstImage}"
android:id="@+id/imageView3" />

Crash after migration to 2.2

Can't make LastAdapter work on complex lists after migration to 2.2
So far I rollback all changes and keep using 2.0

05-02 17:58:39.019 E/AndroidRuntime: FATAL EXCEPTION: main
                                     Process: com.ninetyseconds.auckland.debug, PID: 7837
                                     kotlin.KotlinNullPointerException
                                         at com.github.nitrico.lastadapter.LastAdapter$onCreateViewHolder$1.onPreBind(LastAdapter.kt:94)
                                         at android.databinding.ViewDataBinding$4.onNotifyCallback(ViewDataBinding.java:118)
                                         at android.databinding.ViewDataBinding$4.onNotifyCallback(ViewDataBinding.java:112)
                                         at android.databinding.CallbackRegistry.notifyCallbacks(CallbackRegistry.java:201)
                                         at android.databinding.CallbackRegistry.notifyFirst64(CallbackRegistry.java:122)
                                         at android.databinding.CallbackRegistry.notifyRemainder(CallbackRegistry.java:169)
                                         at android.databinding.CallbackRegistry.notifyRecurse(CallbackRegistry.java:145)
                                         at android.databinding.CallbackRegistry.notifyCallbacks(CallbackRegistry.java:91)
                                         at android.databinding.ViewDataBinding.executeBindingsInternal(ViewDataBinding.java:371)
                                         at android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.java:351)
                                         at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:108)
                                         at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:27)
                                         at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6356)
                                         at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:122)
                                         at com.github.nitrico.lastadapter.LastAdapter.onBindViewHolder(LastAdapter.kt:27)
                                         at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6389)
                                         at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5335)
                                         at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5598)
                                         at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440)
                                         at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436)
                                         at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224)
                                         at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:556)
                                         at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
                                         at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
                                         at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
                                         at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3583)
                                         at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3312)
                                         at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3844)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:636)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
                                         at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                         at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1795)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
                                         at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                         at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
                                         at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
05-02 17:58:39.019 E/AndroidRuntime:     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                         at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
                                         at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
                                         at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
                                         at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
                                         at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
                                         at com.android.internal.policy.DecorView.onLayout(DecorView.java:727)
                                         at android.view.View.layout(View.java:17637)
                                         at android.view.ViewGroup.layout(ViewGroup.java:5575)
                                         at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2346)
                                         at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2068)
                                         at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
                                         at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6338)
                                         at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
                                         at android.view.Choreographer.doCallbacks(Choreographer.java:686)
                                         at android.view.Choreographer.doFrame(Choreographer.java:621)
                                         at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
                                         at android.os.Handler.handleCallback(Handler.java:751)
                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                         at android.os.Looper.loop(Looper.java:154)
                                         at android.app.ActivityThread.main(ActivityThread.java:6121)
                                         at java.lang.reflect.Method.invoke(Native Method)
                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)```

IllegalStateException: reference.get() must not be null

Hello.

I use LastAdapter v1.2.0. My code is written in Java. Sometimes when I go back to activity with fragment I use LastAdapter in I get this:

java.lang.IllegalStateException: reference.get() must not be null
    at com.github.nitrico.lastadapter.WeakReferenceOnListChangedCallback.getAdapter(WeakReferenceOnListChangedCallback.kt:30)
    at com.github.nitrico.lastadapter.WeakReferenceOnListChangedCallback.onItemRangeInserted(WeakReferenceOnListChangedCallback.kt:41)
    at android.databinding.ListChangeRegistry$1.onNotifyCallback(ListChangeRegistry.java:47)
    at android.databinding.ListChangeRegistry$1.onNotifyCallback(ListChangeRegistry.java:38)
    at android.databinding.CallbackRegistry.notifyCallbacks(CallbackRegistry.java:201)
    at android.databinding.CallbackRegistry.notifyFirst64(CallbackRegistry.java:122)
    at android.databinding.CallbackRegistry.notifyRemainder(CallbackRegistry.java:169)
    at android.databinding.CallbackRegistry.notifyRecurse(CallbackRegistry.java:145)
    at android.databinding.CallbackRegistry.notifyCallbacks(CallbackRegistry.java:91)
    at android.databinding.ListChangeRegistry.notifyCallbacks(ListChangeRegistry.java:135)
    at android.databinding.ListChangeRegistry.notifyInserted(ListChangeRegistry.java:93)
    at android.databinding.ObservableArrayList.notifyAdd(ObservableArrayList.java:118)
    at android.databinding.ObservableArrayList.addAll(ObservableArrayList.java:60)
    ...

Question: How to Set Single Selection Item?

Is it possible (in a easy way) to create a single selection list using LastAdapter? I would like to have a list of items and be able to set an item as selected. Whenever the user selects another item, the first item should be deselected and the new item selected.

Thanks!

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.