Я столкнулся с довольно уклончивой проблемой при разработке приложения для Android.Приложение является клиентом сервиса криптовалюты RESTFul.В простейшем виде он извлекает информацию о диапазоне виртуальных монет и отображает их в списке, представленном с использованием компонента RecycleView.
Проблема заключается в том, что список монет иногда отображается так, как ожидается, см. Ниже.
в другое время, однако это не удалось сделать, даже моя строка отладки говорит мне, что данные были получены.В последнем случае список будет отображаться, когда я перетаскиваю и опускаю экран (о да, я добавил SwipeRefreshLayout в свой класс Fragment и реализовал необходимые элементы).
Приложение было разработано с использованием шаблона MVP, соответствующий код выглядит следующим образом:
Класс интерактора действует как серверная служба, которая извлекает данные JSON через службу RESTFul, используются OKHttp lib и RxJava:
@Override
public Observable<List<Coin>> fetchCoins(){
//TODO
return Observable.fromCallable(this::getCoinList);
}
private List<Coin> getCoinList() throws IOException, JSONException {
Request request = RequestGenerator.get(Api.BIT_COINS_LIST);
String response = requestHandler.request(request);
List<Coin> coinList = CoinListingParser.parse(response);
return coinList;
}
Класс презентатора соединяет данные, извлекаемые из интерактора и класса представления:
@Override
public void fetchCoins() {
showLoading();
fetchSubscription = coinListingInteractor.fetchCoins().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onCoinFetchSuccess, this::onCoinFetchFailed);
}
private void onCoinFetchSuccess(List<Coin> list)
{
Log.d("CoinListing", "fetch succeeded");
if (isViewAttached())
{
coinListView.showCoins(list);
coinListView.loaded();
}
}
Класс фрагмента реализует класс coinListView и реализует метод showCoins, который мы видели в классе презентатора, такчто данные и компоненты GUI связаны между собой - ButterKnife используется для краткого и ясного кода:
public class CoinListingFragment extends Fragment implements CoinListingView,SwipeRefreshLayout.OnRefreshListener {
@Inject
CoinListingPresenter coinPresenter;
@Bind(R.id.coin_listing)
RecyclerView coinListRecycleView;
@Bind(R.id.swipe_container)
SwipeRefreshLayout mSwipeRefreshLayout;
private RecyclerView.Adapter adapter;
private List<Coin> coinList = new ArrayList<>(20);
@Override
public void showCoins(List<Coin> list) {
this.coinList.clear();
this.coinList.addAll(list);
coinListRecycleView.setVisibility(View.VISIBLE);
adapter.notifyDataSetChanged();
}
@Override
public void onResume(){
super.onResume();
getActivity().runOnUiThread(()-> {coinPresenter.fetchCoins();});
}
}
Сопутствующий класс RecycleView.Adapter выглядит следующим образом:
public class CoinListingAdapter extends RecyclerView.Adapter<CoinListingAdapter.ViewHolder>{
private List<Coin> coinList;
private Context context;
private CoinListingView view;
public CoinListingAdapter(List<Coin> list, CoinListingView coinView)
{
this.coinList = list;
view = coinView;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
context = parent.getContext();
View rootView = LayoutInflater.from(context).inflate(R.layout.fragment_coin_list_grid, parent, false);
return new ViewHolder(rootView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemView.setOnClickListener(holder);
holder.coin = coinList.get(position);
holder.name.setText(holder.coin.getFullName()+"("+holder.coin.getName()+")");
Picasso.with(context).load(holder.coin.getImageUrl()).into(holder.img);
holder.price.setText(holder.coin.getPrice());
}
@Override
public int getItemCount() {
return coinList.size();
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
@Bind(R.id.coin_name)
public TextView name;
@Bind(R.id.image_thumb)
public ImageView img;
@Bind(R.id.coin_price)
public TextView price;
public Coin coin;
public ViewHolder(View root)
{
super(root);
ButterKnife.bind(this, root);
}
}
}