0

Активность моего запуска - TabLayout, на котором размещены несколько ниже фрагментов. Видение заключается в том, что при каждом нажатии на вкладку OnCreate Fragment будет использовать библиотеку Retrofit2 для получения данных с сервера и отображения данных через RecyclerView onCreateView.Как отложить создание фрагмента фрагмента до тех пор, пока не будет разрешен запрос GET с сервера?

В настоящее время приложение запускается при запуске, так как onCreateView заканчивается первым и хочет отображать данные до того, как асинхронный запрос GET даже завершится. В частности, метод getItemCount внутреннего класса ModelHolder создает ссылку на нулевой объект.

У меня есть две идеи отложить создание представления Фрагмента до тех пор, пока запрос GET не завершится, так что на самом деле на экране будут отображаться данные.

1) Принудительная синхронизация на фрагменте, так что onCreate придется заканчивать до того, как onCreateView даже начнется. Приложение замерзнет на несколько мгновений, но оно не будет разбиваться, как раньше.

2) Добавьте экран Splash и сделайте его активным, чтобы пользователь смотрел экран Splash при загрузке данных. Я думаю, что это обман, потому что это уклоняется от проблемы.

Каков наилучший способ задержки onCreateView? Если подход не является хорошей практикой, какие альтернативные решения существуют?

public class ModelsFragment extends Fragment { 

private final String API_KEY = "INSERT API KEY HERE"; 

private static final String ARG_CATEGORY = "model_category"; 
private String mCategory; 

private RecyclerView mModelRecyclerView; 
private ModelAdapter mModelAdapter; 

private List<Model> mModels; 

public static Fragment newInstance(String category) { 
    Bundle args = new Bundle(); 
    args.putString(ARG_CATEGORY, category); 
    ModelsFragment modelsFragment = new ModelsFragment(); 
    modelsFragment.setArguments(args); 

    return modelsFragment; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mCategory = getArguments().getString(ARG_CATEGORY); 

    EdmundsService service = EdmundsServiceGenerator.createService(EdmundsService.class); 

    Map<String, String> options = new HashMap<>(); 
    options.put("state", "new"); 
    options.put("year", "2016"); 
    options.put("view", "basic"); 
    options.put("api_key", API_KEY); 
    if (mCategory != null) { 
     options.put("category", mCategory); 
    } 

    Call<Models> call = service.getModels(options); 
    call.enqueue(new Callback<Models>() { 
     @Override 
     public void onResponse(Call<Models> call, Response<Models> response) { 
      if (response.isSuccessful()) { 
       mModels = response.body().getModels(); 
       Log.i("GET Status", "Successfully retrieved data"); 
       Log.i("GET Status", response.body().getModelsCount().toString()); 
      } 
      else { 
       Log.i("GET Status", "Failed to retrieve data"); 
      } 
     } 

     @Override 
     public void onFailure(Call<Models> call, Throwable t) { 
      Log.e("Error retrieving data", t.getMessage()); 
     } 
    }); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

    mModelRecyclerView = (RecyclerView) inflater.inflate(R.layout.fragment_models, container, false); 
    updateUI(); 
    mModelRecyclerView.setHasFixedSize(true); 
    mModelRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 

    return mModelRecyclerView; 
} 

private void updateUI() { 
    mModelAdapter = new ModelAdapter(mModels); 
    mModelRecyclerView.setAdapter(mModelAdapter); 
} 

public class ModelHolder extends RecyclerView.ViewHolder { 
    public ModelHolder(LayoutInflater inflater, ViewGroup parent) { 
     super(inflater.inflate(R.layout.fragment_models_card_view_item, parent, false)); 

    } 
} 

public class ModelAdapter extends RecyclerView.Adapter<ModelHolder> { 
    // Set number of Cards in the recycler view. 
    private List<Model> models; 

    public ModelAdapter(List<Model> models) { 
     this.models = models; 
    } 

    @Override 
    public ModelHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     return new ModelHolder(LayoutInflater.from(parent.getContext()), parent); 
    } 

    @Override 
    public void onBindViewHolder(ModelHolder holder, int position) { 

    } 

    @Override 
    public int getItemCount() { 
     return models.size(); 
    } 
} 

} 

ответ

0

Вы можете исправить сбой, имея getItemCount() чек на нуль.

@Override 
public int getItemCount() { 
    return models == null ? 0 : models.size(); 
} 

Затем в вашем дооснащения onResponse(), просто вызовите updateUI, чтобы заполнить ваш ModelAdapter.

РЕДАКТИРОВАТЬ: Чтобы решить ваши две идеи, заставить поток ui ждать, пока вы получите ответ сервера, может привести к ANR и пользователю, закрывающему ваше приложение. Представьте, что произойдет, если у них плохое соединение, и для получения данных требуется 10 секунд. Для идеи номер два довольно распространено, чтобы показывать ProgressBar при загрузке данных, а затем переключать свою видимость, когда данные готовы. Цель onCreateView() - просто вернуть представление; привязка данных может произойти позже.

 Смежные вопросы

  • Нет связанных вопросов^_^