Дано:
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 и статья на Хабре
Комментариев нет:
Отправить комментарий