Collectionの特定の位置に要素を追加したい
解決したいこと
RealmとRecyclerViewでtodoアプリを作成したいです。
ドラッグアンドドロップでリスト項目の並び替えを実装するために、ItemTouchHelperを使っています。
onMove()の中でドラッグした項目をドロップした位置に移動したいのですが、
add(int 追加位置, Object 追加する要素)のメソッドを使うとdeprecatedのエラーが出てしましい、このメソッドを実行した時点でアプリが落ちてしまいます。
発生している問題・エラー
上記add()のdeprecatedエラーが出てしまい、実装方法が分からず困っています。
代替となるメソッドを探したのですが、いっこうに見つからないので初めて質問をします。説明不足な点があったらすみません。
宜しくお願いします。
```
E/InputEventReceiver: Exception dispatching input event.
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.simpletodo, PID: 15243
java.lang.UnsupportedOperationException: This method is not supported by 'RealmResults' or 'OrderedRealmCollectionSnapshot'.
at io.realm.OrderedRealmCollectionImpl.add(OrderedRealmCollectionImpl.java:528)
at io.realm.RealmResults.add(RealmResults.java:69)
at com.example.simpletodo.MainActivity$onCreate$itHelper$1$onMove$1.execute(MainActivity.kt:80)
at io.realm.Realm.executeTransaction(Realm.java:1489)
at com.example.simpletodo.MainActivity$onCreate$itHelper$1.onMove(MainActivity.kt:76)
at androidx.recyclerview.widget.ItemTouchHelper.moveIfNecessary(ItemTouchHelper.java:881)
at androidx.recyclerview.widget.ItemTouchHelper$2.onTouchEvent(ItemTouchHelper.java:387)
at androidx.recyclerview.widget.RecyclerView.dispatchToOnItemTouchListeners(RecyclerView.java:3124)
at androidx.recyclerview.widget.RecyclerView.onTouchEvent(RecyclerView.java:3283)
at android.view.View.dispatchTouchEvent(View.java:12513)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3024)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2705)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3030)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2719)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:440)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1830)
at android.app.Activity.dispatchTouchEvent(Activity.java:3400)
at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:398)
at android.view.View.dispatchPointerEvent(View.java:12752)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5106)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4909)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4426)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4479)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4445)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4585)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4453)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4642)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4426)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4479)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4445)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4453)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4426)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7092)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7061)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7022)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7195)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:186)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
E/AndroidRuntime: at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:177)
at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:7166)
at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:7218)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:690)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process: Sending signal. PID: 15243 SIG: 9
### 該当するソースコード
```kotlin
package com.example.simpletodo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.CheckBox
import android.widget.EditText
import android.widget.TextView
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.realm.Realm
import io.realm.RealmResults
import io.realm.kotlin.createObject
import io.realm.kotlin.where
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.todo_list_row.*
class MainActivity : AppCompatActivity() {
private lateinit var realm: Realm
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//タスクバーの非表示
supportActionBar?.hide()
//realmのインスタンスを取得
realm = Realm.getDefaultInstance()
//レイアウトマネージャーの設定
list.layoutManager = LinearLayoutManager(this)
//TodoのCollectionを返す
val todos = realm.where<Todo>().findAll()
val adapter = TodoAdapter(todos)
list.adapter = adapter
//saveボタン押下時に、新しいtodoを登録
save.setOnClickListener {
val todo: String = addTodo.text.toString()
if (!"".equals(todo)) {
realm.executeTransaction {
val maxId = it.where<Todo>().max("id")
val nextId = (maxId?.toLong() ?: 0L) + 1
//Primary Keyを与えて、引数型のオブジェクトを生成する
val newTodo = it.createObject<Todo>(nextId)
newTodo.todo = todo
//追加後は空文字に戻す
addTodo.setText("")
}
}
}
//fab押下時、チェック済みのtodoを一括削除
fab.setOnClickListener {
realm.executeTransaction {
realm.where<Todo>().equalTo("isChecked", true).findAll().deleteAllFromRealm()
//adapter positionを合わせるため、データセットの変更を伝える
adapter.notifyDataSetChanged()
}
}
//ItemTouchHelper
val itHelper = ItemTouchHelper(
object: ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.LEFT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val fromPosition = viewHolder?.adapterPosition
val toPosition = target?.adapterPosition
realm.executeTransaction {
//ここでドロップ位置にドラッグしている項目を挿入したいです
val movingTodo = todos.get(fromPosition)
todos.deleteFromRealm(fromPosition)
todos.add(toPosition, movingTodo)
}
//Adapterにドラッグアンドドロップされたことを通知します。
adapter.notifyItemMoved(fromPosition, toPosition)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
viewHolder.let {
realm.executeTransaction {
todos.deleteFromRealm(viewHolder.adapterPosition)
}
adapter.notifyItemRemoved(viewHolder.adapterPosition)
}
}
}
)
itHelper.attachToRecyclerView(list)
}
override fun onDestroy() {
super.onDestroy()
realm.close()
}
}