Retrofit rxjava中onNext获取数据
Get data from onNext in Retrofit rxjava
这里的列表(list.get(9) 部分)是一个字符串 ArrayList。我试图从用户那里获取所有用户名并将其添加到列表中,然后在文本视图中显示第 10 个名称。
当我 运行 应用程序时,它会在我下面链接的图像中抛出错误,错误是 textView.setText(list.get(9)) 中的索引超出范围。但是当我评论这一行并使用按钮 onclick 为我的文本视图设置文本时它起作用了。
这是我示例中的 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
好的,问题是 myAPI.getUsers()
是 io
线程中的 运行,这需要时间来完成并用用户名填充 list
。另一方面,textView.setText(list.get(9));
立即触发。因此,正确的流程是将textView.setText(list.get(9));
放在onNext
或onComplete
中,这些方法会在myAPI.getUsers()
结束时触发
你在 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));
}
您的代码中有一些错误可能会导致 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
方法被调用,然后再对结果进行任何操作。
这里的列表(list.get(9) 部分)是一个字符串 ArrayList。我试图从用户那里获取所有用户名并将其添加到列表中,然后在文本视图中显示第 10 个名称。
当我 运行 应用程序时,它会在我下面链接的图像中抛出错误,错误是 textView.setText(list.get(9)) 中的索引超出范围。但是当我评论这一行并使用按钮 onclick 为我的文本视图设置文本时它起作用了。
这是我示例中的 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
好的,问题是 myAPI.getUsers()
是 io
线程中的 运行,这需要时间来完成并用用户名填充 list
。另一方面,textView.setText(list.get(9));
立即触发。因此,正确的流程是将textView.setText(list.get(9));
放在onNext
或onComplete
中,这些方法会在myAPI.getUsers()
结束时触发
你在 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));
}
您的代码中有一些错误可能会导致 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
方法被调用,然后再对结果进行任何操作。