【问题标题】:Get data from onNext in Retrofit rxjava从 Retrofit rxjava 中的 onNext 获取数据
【发布时间】:2019-07-04 04:53:26
【问题描述】:

这里的列表(部分是 list.get(9) )是一个字符串数组列表。我试图从用户那里获取所有用户名并将其添加到列表中,然后在文本视图中显示第 10 个名称。

当我运行应用程序时,它会在我下面链接的图像中引发错误,错误是 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

【问题讨论】:

  • onNext之外是什么意思?
  • 你能分享你的异常堆栈跟踪吗?
  • @BachVu 对不起,伙计们,这是我第一次在 stackoverflow 中询问。我已经编辑了我的帖子以使其更易于理解。请再次检查,谢谢。
  • @raxerz 抱歉,这是我第一次在 stackoverflow 中询问。我已经编辑了我的帖子以使其更易于理解。请再次检查,谢谢

标签: android retrofit rx-java


【解决方案1】:

您的代码中有一些错误可能导致IndexOutOfBoundsException

我会在你的代码中加入一些 cmets:

@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 方法。

【讨论】:

  • 谢谢,我现在明白了这个问题,但我想从 onCreate 访问用户列表。有没有机会这样做还是不可能?
  • 为什么要在onCreate中访问它?这是不可能的,因为它主要取决于网络速度。从端点检索数据时,您应该显示loading
  • 您必须在 onNext 中执行此操作,因为这是您确保接收到数据的唯一地方。如果您访问 onCreate 中的列表,您将不会有一致的行为,因为端点可能已回答或未回答。唯一可以确保它已回答的地方是 onNext。
  • 谢谢,这个问题我想了很久。绿色检查你的答案。
【解决方案2】:

好的,问题是myAPI.getUsers()io 线程中运行,这需要时间来完成并用用户名填充list。另一方面,textView.setText(list.get(9)); 会立即触发。所以正确的流程是把textView.setText(list.get(9));放到onNext或者onComplete里面,这些方法会在myAPI.getUsers()完成时触发

【讨论】:

  • 哦,谢谢,我现在明白了,但是有什么方法可以在 onCreate 中使用 ArrayList 用户。我真的很想获得该列表并与 OnNext() 分开使用
【解决方案3】:

您在 onCreate 方法中调用 textView.setText(list.get(9));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));
}

【讨论】:

  • 是的,我知道调用 textView.setText(list.get(9));在 onNext 中将起作用,但我想要的是在 onCreate 中使用 ArrayList 用户。我不想在 onNext 中做所有事情。我使用 for 循环将此数组复制到名为 list 的新数组中,但它不起作用
猜你喜欢
  • 2018-09-09
  • 2018-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2020-02-15
相关资源
最近更新 更多