Преобразовать код RxJava в Kotlin правильно

Я изучаю как Котлин, так и RxJava. Я hava такой код в Java:

public class MainActivity extends AppCompatActivity { private HashMap<String, Object> cacheToInsertToDb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); cacheToInsertToDb = new HashMap<>(); Observable.interval(1, TimeUnit.SECONDS) .take(30) // up to 30 items .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Long>() { @Override public void accept(Long aLong) throws Exception { cacheToInsertToDb.put(aLong+"", aLong); Log.d("Observable", cacheToInsertToDb.values().toString()); } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { } }, new Action() { @Override public void run() throws Exception { } }); Observable.interval(10, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Long>() { @Override public void accept(Long aLong) throws Exception { proceedVlues(cacheToInsertToDb.values()); cacheToInsertToDb.clear(); Log.d("CLEARED", cacheToInsertToDb.values().toString()); } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { } }, new Action() { @Override public void run() throws Exception { } }); } private void proceedVlues(Collection<Object> values) { for(Object v: values){ if(v instanceof Long){ Log.d("proceedVlues", v+""); } } } } 

Однако, когда я конвертирую его в AndroidStudio, в среде IDE есть куча ошибок.

Вот этот код в Kotlin, преобразованный в Android Studio:

 class MainActivity : AppCompatActivity() { private var cacheToInsertToDb: HashMap<String, Any>? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) cacheToInsertToDb = HashMap() Observable.interval(1, TimeUnit.SECONDS) .take(30) // up to 30 items .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Consumer<Long> { @Throws(Exception::class) override fun accept(aLong: Long?) { cacheToInsertToDb!!.put(aLong!!.toString() + "", aLong) Log.d("Observable", cacheToInsertToDb!!.values.toString()) } }, Consumer { }, Action { }) Observable.interval(10, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Consumer<Long> { @Throws(Exception::class) override fun accept(aLong: Long?) { proceedVlues(cacheToInsertToDb!!.values) cacheToInsertToDb!!.clear() Log.d("CLEARED", cacheToInsertToDb!!.values.toString()) } }, Consumer { }, Action { }) } private fun proceedVlues(values: Collection<Any>) { for (v in values) { if (v is Long) { Log.d("proceedVlues", v.toString() + "") } } } } 

Это дает мне ошибку, подчеркивая «неразрешенную ссылку на @Throws» и «accept» переопределяет nothig ». Как я могу правильно преобразовать этот код Java в Kotlin?

В kotlin вы можете заменить реализации интерфейсов, имея только один метод, для лямбда-выражения ( doc ).

Как и Java 8, Kotlin поддерживает конверсии SAM. Это означает, что литералы функции Kotlin могут быть автоматически преобразованы в реализации интерфейсов Java с помощью одного метода, отличного от метода по умолчанию, если типы параметров метода интерфейса соответствуют типам параметров функции Kotlin.

Это дает вам:

 .subscribe( { item: Long? -> }, { t: Throwable -> }, {//onComplete }) 

также, в зависимости от того, используете ли вы RxJava2 ( doc ):

RxJava 2.x больше не принимает нулевые значения, и следующее приведет к немедленному выводу NullPointerException или в качестве сигнала

Из-за этого вы уверены, что не получаете нуль в своем onNext и вы можете удалить проверку с безопасным нулем ?

 .subscribe( { item: Long -> }, { t: Throwable -> }, {//onComplete }) 

Вы можете обновить свой код, используя безопасные npe и lambdas. Иногда код, преобразованный из java в kotlin, нуждается в некоторых косметических штрихах.

  .subscribe(object : Consumer<Long> { @Throws(Exception::class) override fun accept(aLong: Long?) { cacheToInsertToDb!!.put(aLong!!.toString() + "", aLong) Log.d("Observable", cacheToInsertToDb!!.values.toString()) } }, Consumer { }, Action { }) 

в

 .subscribe(Consumer<Long?>{ aLong -> cacheToInsertToDb?.put(aLong?.toString() ?: "", aLong) Log.d("Observable", cacheToInsertToDb?.values.toString()) }, Consumer { }, Action { })