Страницы

Поиск по вопросам

среда, 10 июля 2019 г.

Retrofit 2 : Как получить response.body из UI-потока?

Дано:
RecyclerView из элементов CardView. За RecyclerView отвечает ManagerListAdapter, в конструктор которого передаётся ArrayList при создании экземпляра. Элементы ArrayList заполняют CardView в ManagerListAdapter.
Это всё работает корректно.
Задача:
В конструктор ManagerListAdapter при создании его экземпляра передавать ArrayList, полученный с JSON с использованием Retrofit 2.
Проблема:
Как говорит гугл, в UI потоке нельзя создавать подобные GET-запросы, нужно использовать асинхронный поток через .enuque
При этом, ManagerListAdapter можно создавать только в UI-потоке.
Вопрос:
Как корректно передать полученный с JSON ArrayList в конструктор адаптера ManagerListAdapter?
Быть может, я использую не совсем тот подход?
Инициализация RecyclerView в одном из Fragment
private void initRecyclerView() { RecyclerView managersRecyclerView = (RecyclerView) view.findViewById(R.id.managersRecyclerView); managersRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); managersRecyclerView.setAdapter(new ManagerListAdapter(getManagers()));

// getRemoteManagers();
}
private void getRemoteManagers() {
ApiObject client = ServiceGenerator.createService(ApiObject.class); Call> call = client.getManagers();
call.enqueue(new Callback>() { @Override public void onResponse(Call> call, Response> response) {
if (response.isSuccessful()) {
List managers = response.body(); //Эту коллекцию я хочу добавить в конструктор ManagerListAdapter sortManagers(managers);
}
}
@Override public void onFailure(Call> call, Throwable t) {
} });
}
private List getManagers() {
//Заглушка для тестирования, локальный вариант.
List managers = new ArrayList<>();
managers.add(new ManagerDTO("Alex Pavlov", 100)); managers.add(new ManagerDTO("Ivan Pavlov", 95)); managers.add(new ManagerDTO("Petr Pavlov", 99)); managers.add(new ManagerDTO("Stepan Pavlov", 100)); managers.add(new ManagerDTO("Azik Pavlov", 100)); managers.add(new ManagerDTO("Azik Myand", 100)); managers.add(new ManagerDTO("Azik Specca", 50)); managers.add(new ManagerDTO("Azik Kane", 0)); managers.add(new ManagerDTO("Azik McDonald", 99)); managers.add(new ManagerDTO("Azik Jagr", 1));
sortManagers(managers);
return managers;
}
Этот вопрос так же задавал на англоязычном стеке:
How to get response from other thread using Retrofit 2.0

UPDATE 18.07
ServiceGenerator
public class ServiceGenerator {
private static final String URL = "https://api.myjson.com/bins/"; private static Retrofit.Builder builder = new Retrofit.Builder() .addCallAdapterFactory(RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io())) .baseUrl(URL) .addConverterFactory(JacksonConverterFactory.create());
public static S createService(Class serviceClass) {
Retrofit retrofit = builder.build(); return retrofit.create(serviceClass); }
ApiObject
import java.util.List;
import retrofit2.http.GET; import rx.Observable;


public interface ApiObject {
@GET("11p73.json") Observable> getManagers();
}
getRemoteManagers
private void getRemoteManagers() {
ApiObject client = ServiceGenerator.createService(ApiObject.class);
Observable> managers = client.getManagers(); managers .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber>() { @Override public void onCompleted() {
//do nothing }
@Override public void onError(Throwable e) {
Log.e("OnError", "Not good"); }
@Override public void onNext(List managers) {
RecyclerView managersRecyclerView = (RecyclerView) view.findViewById(R.id.managersRecyclerView); managersRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); managersRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); managersRecyclerView.setAdapter(new ManagerListAdapter(managers)); } });
}
Log:
07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat E/AndroidRuntime: FATAL EXCEPTION: main Process: ru.alexbykov.sailesstat, PID: 4442 java.lang.NoClassDefFoundError: Failed resolution of: Lretrofit2/adapter/rxjava/RxJavaCallAdapterFactory; at ru.alexbykov.sailesstat.remote.dto.ServiceGenerator.(ServiceGenerator.java:17) at ru.alexbykov.sailesstat.statistic.fragments.tabSales.ManagersFragment.getRemoteManagers(ManagersFragment.java:73) at ru.alexbykov.sailesstat.statistic.fragments.tabSales.ManagersFragment.initRecyclerView(ManagersFragment.java:67) at ru.alexbykov.sailesstat.statistic.fragments.tabSales.ManagersFragment.onCreateView(ManagersFragment.java:59) at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617) at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570) at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) at android.support.v4.view.ViewPager.populate(ViewPager.java:1177) at android.support.v4.view.ViewPager.populate(ViewPager.java:1025) at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1545) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:668) at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:735) at android.view.View.measure(View.java:17547) at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1075) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.FrameLayout.onMeasure(FrameLayout.java:436) at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436) at android.widget.LinearLayout.measureVertical(LinearLayout.java:722) at android.widget.LinearLayout.onMeasure(LinearLayout.java:613) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.FrameLayout.onMeasure(FrameLayout.java:436) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436) at android.widget.LinearLayout.measureVertical(LinearLayout.java:722) at android.widget.LinearLayout.onMeasure(LinearLayout.java:613) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.FrameLayout.onMeasure(FrameLayout.java:436) at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2615) at android.view.View.measure(View.java:17547) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885) 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 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: exClass=java.lang.ClassNotFoundException 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: exMsg=Didn't find class "retrofit2.adapter.rxjava.RxJavaCallAdapterFactory" on path: DexPathList[[dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-support-annotations-23.3.0_5de1f4990c3728db7199bf5c90bfdb9def350a94-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-retrofit-2.1.0_8b8f8e10a24e9cbb87d2817f40dae9b260cf7282-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-okio-1.8.0_b8b5a990379e0c2ac791ab0c60e6d287203675f2-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-okhttp-3.3.0_866858d020e75cefeef6ab6b91a11fd0f01f1cad-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-jackson-databind-2.7.2_16e021f670fa80a4e5bff4cbb34bd38f737d85f8-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-jackson-core-2.7.2_dda0286f28d26c1864b8b07e760d8e17be822281-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-jackson-annotations-2.7.0_7ca878bfbcac373c0abd0f8db967beedc4f2d50f-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-internal_impl-23.3.0_7d4478fe63824ec180d999bac79eed2e00dfbdcd-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-converter-jackson-2.1.0_fb2f5790154a81f89b59fa9475c841489aa12048-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.jakewharton-butterknife-8.1.0_8235e6ed1a224a7cff79b1e0e63f739474e0008a-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-support-vector-drawable-23.3.0_a8eb97e4d985983e20b47dc6def5331594cf0d7c-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-support-v4-23.3.0_04c4d80e6e44a7b94ad5796f30419a8aafdc4608-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-recyclerview-v7-23.3.0_0274d8817f144b6caeef34836695e068a055782a-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-design-23.3.0_6836fcb43ed2de008a5ece0a6c80bfe80babf58c-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-cardview-v7-23.3.0_bb32e1ecd443ace6a7a6ef2db7a64f3647077cc0-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-appcompat-v7-23.3.0_49ad66e001493b50a4c053b5bd9f87269fbc7ec1-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-com.android.support-animated-vector-drawable-23.3.0_88f27537c1bceae88b9a0d4e5f96b37399657141-classes.dex", dex file "/data/data/ru.alexbykov.sailesstat/files/instant-run/dex/slice-butterknife-annotations-8.1.0_ba06f0ea21d2a585450c9fb25457676f0e115968-classes.dex"],nativeLibraryDirectories=[/vendor/lib, /system/lib, /vendor/lib, /system/lib]] 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: file=BaseDexClassLoader.java 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: class=dalvik.system.BaseDexClassLoader 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: method=findClass line=56 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: stack=java.lang.NoClassDefFoundError: Failed resolution of: Lretrofit2/adapter/rxjava/RxJavaCallAdapterFactory; at ru.alexbykov.sailesstat.remote.dto.ServiceGenerator.(ServiceGenerator.java:17) at ru.alexbykov.sailesstat.statistic.fragments.tabSales.ManagersFragment.getRemoteManagers(ManagersFragment.java:73) at ru.alexbykov.sailesstat.statistic.fragments.tabSales.ManagersFragment.initRecyclerView(ManagersFragment.java:67) at ru.alexbykov.sailesstat.statistic.fragments.tabSales.ManagersFragment.onCreateView(ManagersFragment.java:59) at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617) at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570) at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) at android.support.v4.view.ViewPager.populate(ViewPager.java:1177) at android.support.v4.view.ViewPager.populate(ViewPager.java:1025) at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1545) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:668) at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:735) at android.view.View.measure(View.java:17547) at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1075) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.FrameLayout.onMeasure(FrameLayout.java:436) at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436) at android.widget.LinearLayout.measureVertical(LinearLayout.java:722) at android.widget.LinearLayout.onMeasure(LinearLayout.java:613) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.FrameLayout.onMeasure(FrameLayout.java:436) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436) at android.widget.LinearLayout.measureVertical(LinearLayout.java:722) at android.widget.LinearLayout.onMeasure(LinearLayout.java:613) at android.view.View.measure(View.java:17547) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535) at android.widget.FrameLayout.onMeasure(FrameLayout.java:436) at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2615) at android.view.View.measure(View.java:17547) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885) 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. 07-18 06:29:43.706 4442-4442/ru.alexbykov.sailesstat D/Error: ERR: TOTAL BYTES WRITTEN: 36252 07-18 06:29:47.845 4442-4442/ru.alexbykov.sailesstat I/Process: Sending signal. PID: 4442 SIG: 9


Ответ

Чтобы выполнить что-то в UI потоке в активити у неё есть метод runOnUiThread(Runnable run)
Т.е. оберните нужный код так:
runOnUiThread(new Runnable() { @Override public void run() { //код тут выполнится в основном потоке. } });

Также можно приспособить сюда RxJava. Вот вопрос с SO, вот репозиторий на GitHub и статья на Хабре

Комментариев нет:

Отправить комментарий