如何将Fragment UI创建延迟到服务器的GET请求解决之后?

吉米·肖(Jimmy Shaw)

我的启动器活动是一个TabLayout,其中包含以下几个片段。愿景是,在每次单击Tab时,Fragment的onCreate将使用Retrofit2库从服务器获取数据并通过onCreateView的RecyclerView显示数据。

当前,该应用程序在启动时崩溃,因为onCreateView首先完成,并且想要在异步GET请求甚至完成之前显示数据。具体来说,内部类ModelHolder的getItemCount方法产生一个空对象引用。

我有两个想法可以将Fragment的视图创建延迟到GET请求完成之后,以便视图实际上具有要显示的数据。

1)在Fragment上强制同步,以便onCreate必须在onCreateView开始之前完成。该应用程序将冻结一会儿,但不会像以前那样崩溃。

2)添加一个启动屏幕并使其成为启动程序活动,以便用户在加载数据时查看启动屏幕。我认为这很骗人,因为它可以避免问题。

延迟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();
    }
}

}
国际象棋

您可以通过getItemCount()检查null来解决崩溃问题

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

然后,在改造中onResponse(),只需调用updateUI即可填充ModelAdapter。

编辑:要解决您的两个想法,强制ui线程等待,直到您收到服务器响应,可能会导致ANR,并且用户关闭了您的应用程序。想象一下,如果他们的连接不良并且需要10秒钟来获取数据,将会发生什么情况。对于第二个想法,在加载数据时显示一个ProgressBar,然后在数据准备好后切换其可见性是很常见的。的目的onCreateView()仅仅是返回视图;数据绑定可以稍后进行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将侦听器从Fragment传递到DialogFragment?

将服务呼叫延迟到循环之后

如何解决roblox中的服务器延迟

如何将渲染延迟到promise的then()完成之前?

如何将PageRenderer / Fragment / View中的ZXing扫描器嵌入Xamarin.Forms ContentPage中?

如何将常量值和api get请求一起发送到节点服务器

JFOREX SDK-如何将HTTPS GET请求发送到www服务器ssl连接

如何将HTTPS请求重定向到HTTP服务器?

如何将所有服务器请求重定向到Firebase Hosting中的功能

Nginx模块编写:如何将请求转发到服务器?

如何将请求永久发送到我的http服务器

我的Web服务器如何将Web请求发送到IoT设备?

如何将AJAX请求中的ID列表传递给MVC中的服务器

使用akka http,如何将请求标头注入服务器中的传入路由?

如何将NodeJS请求分发到多个服务器并合并结果

HTTP服务器应如何将请求参数传递给脚本?

如何将请求从Web服务器发送到android?

如何将React发送到Express服务器获取请求传递ID

node.js服务器如何将并发请求排队

如何将Ajax请求发送到同一服务器的不同URL

如何将DNS请求路由到特定的DNS服务器?

如何将jquery请求从服务器直接转发到另一个服务器?

如何将$ stateParams从ui路由器传递到服务以解决?

如果在 Reactjs 中重复发送服务器请求,我该如何延迟服务器请求?

如何将数据从服务器放入Kinesis Stream

如何将abook与carddav服务器集成?

如何将文件上传到FTP服务器?

如何将GitLab迁移到新服务器?

如何将Gmail用作Youtrack的SMTP服务器?