【问题标题】:RxJava with AsyncTask and Activity in androidandroid 中带有 AsyncTask 和 Activity 的 RxJava
【发布时间】:2016-07-13 14:42:30
【问题描述】:

我有一个小时使用 RxJava 的经验,我正在尝试在我的项目中实现它,而不是使用接口和侦听器。

我有一个异步任务,它在单独的模块中调用谷歌云端点方法,并在完成后收到List<Profile>

在异步任务的onPostExecute() 方法中,我调用 onNext 以便任何订阅者都收到此数据。

这是AsyncTask 的样子:

private BirthpayApi mApi;
private String mUserId;
private ReplaySubject<List<Profile>> notifier = ReplaySubject.create();

public GetFriends(String userId) {
    mUserId = userId;
}

public Observable<List<Profile>> asObservable() {
    return notifier;
}

@Override
protected List<Profile> doInBackground(Void... params) {
    if (mApi == null) {
        BirthpayApi.Builder builder = new BirthpayApi.Builder(AndroidHttp.newCompatibleTransport(),
                    new AndroidJsonFactory(), null)
                    // options for running against local devappserver
                    // - 10.0.2.2 is localhost's IP address in Android emulator
                    // - turn off compression when running against local devappserver
                    .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                    .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                    @Override
                    public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                            abstractGoogleClientRequest.setDisableGZipContent(true);
                        }
                    });
            mApi = builder.build();
    }

    try {
        return mApi.getFriends(mUserId).execute().getItems();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

@Override
protected void onPostExecute(List<Profile> friends) {
    super.onPostExecute(friends);
    notifier.onNext(friends);
}

然后,在我的 Fragment 中,我想从调用 onNext() 方法的异步任务中收集这些数据。因此,我在声明也扩展了 Fragment 的类时使用implements Action1&lt;List&lt;Profile&gt;&gt;

在来自 Action1 接口的onCall() 方法中,我收集从 Async 任务发送的数据:

@Override
public void call(List<Profile> profiles) {
    if (profiles.size() > 0) {
        updateAdapter(profiles);
    } else
        setUpNoFriendsViews();
}

我跟随树屋,但他们使用一个对象来建模他们的数据,这成为可观察的而不是使用异步类,并且他们使用适配器作为观察者。我做错了吗,无论如何我如何让它工作?

【问题讨论】:

  • 所以您希望您的 observable 在您拨打电话时发出更新的个人资料列表?
  • 然后你想要一个 observable 来观察会改变你的列表的事件,并通过在函数中调用你的 api 将它映射到你更新的列表中。要异步执行此操作,您必须使用 RXbindings 库或调用继续使用您的异步调用
  • 你能给我一个例子吗(用代码)?
  • stackoverflow.com/questions/33415151/… 我提供的答案创建了一个可观察的事件并将其映射到一个字符串。然后我在订阅中打我的休息电话。我所做的有所不同,但它可能会给你一个更好的主意。
  • 这段代码应该放在哪里,activity?

标签: java android android-asynctask rx-java


【解决方案1】:

看起来您并没有订阅您在任何地方创建的 Observable,并且不清楚您在 AsyncTask 上调用执行的位置。我也不认为你想要一个 ReplaySubject 但这取决于你想要达到的目标。

除此之外,我建议完全切换到 Rx,而不是混合 Rx 和 AsyncTasks。在这种情况下,在您的模型类中创建一个类似的方法:

public Observable<List<Profile>> getProfiles() {

    return Observable.defer(new Func0<Observable<List<Profile>>>() {
        @Override
        public Observable<List<Profile>> call() {

            if (mApi == null) {
                BirthpayApi.Builder builder = new BirthpayApi.Builder(AndroidHttp.newCompatibleTransport(),
                        new AndroidJsonFactory(), null)
                        // options for running against local devappserver
                        // - 10.0.2.2 is localhost's IP address in Android emulator
                        // - turn off compression when running against local devappserver
                        .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                        .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                            @Override
                            public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                                abstractGoogleClientRequest.setDisableGZipContent(true);
                            }
                        });
                mApi = builder.build();
            }

            try {
                List<Profile> profiles = mApi.getFriends(mUserId).execute().getItems();
                return Observable.just(profiles);
            } catch (IOException e) {
                return Observable.error(e);
            }
        }
    });
}

然后在你的片段中:

modal.getProfiles()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        new Action1<List<Profile>>() {
                //...
        },
        new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    );

【讨论】:

  • 但这不是推荐的方式。那么推荐的方式会是什么样子。顺便说一句,感谢您的回答。 @Jahnold
  • 当您说“推荐方式”时,您是指 Treehouse 推荐吗?如果您想展示如何将主题与 AsyncTask 一起使用,我可以扩展答案......但我不推荐它!
  • 你会这样做的方式。 @Jahnold
  • 我会像上面那样做!
猜你喜欢
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 2017-09-15
  • 2013-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多