在Retrofit rxjava中从onNext获取数据

时间:2019-07-04 04:53:26

标签: android retrofit rx-java

在这里列表(在list.get(9)的一部分中)是一个String ArrayList。我试图从用户那里获取所有用户名并将其添加到列表中,然后在textview中显示第十个名称。

当我运行该应用程序时,它在下面链接的图像中引发错误,错误是textView.setText(list.get(9))中的索引超出范围。但它在我注释此行并通过使用按钮onclick设置textview的文本时起作用。

这里是我的示例中的api。 https://jsonplaceholder.typicode.com/users

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //init api
    Retrofit retrofit = RetrofitClient.getInstance();
    btnOk = findViewById(R.id.btn_ok);
    myAPI = retrofit.create(IMyAPI.class);
    textView = findViewById(R.id.show);

    //fetchData()

    fetchUserData();

    textView.setText(list.get(9));
    btnOk.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            textView.setText(list.get(9));
        }
    });

}

private void fetchUserData() {
    myAPI.getUsers()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<ArrayList<User>>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(ArrayList<User> users) {
                    String usName ;
                    for(int i = 0; i < users.size(); i++){
                        usName = posts.get(i).getUsername();
                        list.add(usName);
                    }
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });

}

Error in line textView.settext

3 个答案:

答案 0 :(得分:0)

好的,问题是myAPI.getUsers()io线程中运行,这需要时间来完成并用用户名填充list。另一方面,textView.setText(list.get(9));立即被触发。因此,正确的流程是将textView.setText(list.get(9));放在onNextonComplete中,当myAPI.getUsers()完成时将触发这些方法

答案 1 :(得分:0)

textView.setText(list.get(9));仍然为空的情况下,您在onCreate方法中调用list会导致IndexOutOfBoundsException。从onCreate中删除它,并将其放在onNext方法中:

public void onNext(ArrayList<User> users) {
     String usName ;
     for(int i = 0; i < users.size(); i++){
         usName = posts.get(i).getUsername();
         list.add(usName);
     }
     textView.setText(list.get(9));
}

答案 2 :(得分:0)

您的代码中存在一些错误,可能导致IndexOutOfBoundsException

我将在您的代码中添加一些注释:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //init api
    Retrofit retrofit = RetrofitClient.getInstance();
    btnOk = findViewById(R.id.btn_ok);
    myAPI = retrofit.create(IMyAPI.class);
    textView = findViewById(R.id.show);

    fetchUserData();


    // this line should be removed cause you didn't get yet the result of fetchUserData(). Instead you should do this on the onNext method.
    // textView.setText(list.get(9)); 

    btnOk.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Before accessing the list, you must ensure your list contains at least 9 elements. Otherwise it could crash.
            // textView.setText(list.get(9));

            // This would be the correct way
            if (list != null && list.size > 9) {
               textView.setText(list.get(9));
            }
        }
    });

}

private void fetchUserData() {
    myAPI.getUsers()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<ArrayList<User>>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(ArrayList<User> users) {
                    String usName ;
                    for(int i = 0; i < users.size(); i++){
                        usName = posts.get(i).getUsername();
                        list.add(usName);
                    }
                    // This is the place where you are safe to access the users list, so any View component you want to update with the users list should be done here.
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });

}

请记住,您正在使用Rx进行asynchronous调用,在对结果进行任何操作之前,应等待onNext方法被调用。