How to structure my application using MVP with rxjava and modify to get data from Observables?

Therefore, I will try to make this question as accurate as possible, but it will include code fragments that cross the whole encoding.

For context, I'm a fairly new and completely self-help tutorial for Android dev, so please let me know of any obvious misunderstandings / poor organization. The main task of the question is the error that I encountered now, namely: after a network request, the variable that should have been set as a result of this network request is zero, because the code moves forward until the network request is completed.

Here is my activity method. It is assumed that it fills the variable with a mFriendsresult mUserPresenter.getUserList()that (unfortunately) null:

/**
 * Grabs a list of friends, populates list with UserAdapter
 */
@Override
public void onResume(){
    super.onResume();
    mUserPresenter = new UserPresenter();
    mFriends = mUserPresenter.getUserList();
    if (mGridView.getAdapter() == null) {
        UserAdapter adapter = new UserAdapter(getActivity(), mFriends);
        mGridView.setAdapter(adapter);
    }
    else{
        ((UserAdapter)mGridView.getAdapter()).refill(mFriends);
    }

}

This is how I structure the method UserPresenter getUserList:

public List<User> getUserList()
{
    ApiService.get_friends(this);
    return mUserList;
}

Real magic happens in the classroom ApiService:

public static void get_friends(final UserPresenter userPresenter){
    ApiEndpointInterface apiService = prepareService();
    apiService.get_friends().
        observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            new Action1<List<User>>()
            {
               @Override
               public void call(List<User> users) {
                  userPresenter.setList(users);
               }
            }
        );
}

I thought that by calling userPresenter.setList(users)in ApiService, this would set the mUserListapi to respond from the request. However, instead, mUserList == nullat the time of the answer getUserList.

Any ideas on how I can structure this?

+4
source share
1 answer

I also started learning something like that. Here, I prefer to use callbacks.

In his presenter

public void setList(List<User> users) {
    yourView.setUserList(users);
}

And your activity that implements view (MVP)

@Override
public void setUserList(List<User> users) {
    ((UserAdapter)mGridView.getAdapter()).refill(mFriends);
}

, , retrofit .

, . GitHub . ORMLite Picasso, db . ( ). .

:

private DataRetrieverImpl dataRetriever;

@Override
public void getUserList(String name) {
    dataRetriever.getUserList(name);
}

@Override
public void onEvent(DataRetrieverEvent event) {
    UserList userList = (UserList)event.getData();
    mainView.setItems(userList);
}

DataRetrieverImpl ().

private DataRetriever dataRetriever; 
restAdapter = new RestAdapter.Builder().setEndpoint(SERVER_END_POINT).build();
dataRetriever = restAdapter.create(DataRetriever.class);

public void getUserList(final String name) {
    Log.i(TAG, "getting user list for: " + name);

    Observable<UserList> observable = dataRetriever.getUserList(name);

    Log.i(TAG, "subscribe to get userlist");
    observable.subscribe(new Action1<UserList>() {
        @Override
        public void call(UserList userList) {

            eventBus.post(new DataRetrieverEvent("UserList", userList));

            // save to database
            for (User user : userList.getItems()) {
                Log.i(TAG, user.getLogin());
                try {
                    dbHelper.create(user);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
    }, new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            throwable.printStackTrace();
        }
    });
}

DataRetriever - . .

public interface DataRetriever {

    @GET("/search/users")
    public Observable<UserList> getUserList(@Query("q") String name);

}

,

@Override
public void setItems(final UserList userList) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            UserAdapter userAdapter = (UserAdapter)recyclerView.getAdapter();
            userAdapter.setUserList(userList);
            userAdapter.notifyItemRangeInserted(0, userAdapter.getItemCount());
        }
    });
}
+2

Source: https://habr.com/ru/post/1584642/


All Articles