简体   繁体   中英

What is the proper way to call Rx-java Observable methods?

I defined a following method in Wrapper class for making Rest call.

public void getWarehouse(){

    //Generation of  RestAdapter
    RestAdapter adapter = new  RestAdapter.Builder ()
            .setEndpoint(URL)
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .build();

    //Making request to API
    adapter.create(WarehouseAPI.class).getWarehouse()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<List<Warehouse>>() {
                @Override
                public void onCompleted() {
                    Log.d(this.getClass().getName(), "OnCompleted()");
                }

                @Override
                public void onError(Throwable e) {
                    Log.d(this.getClass().getName(), "Error: "  + e.toString());
                }

                @Override
                public void onNext(List<Warehouse> response) {
                }
            });
}

Above code is working fine and I am getting an expected response. But I need to call this method from an Adapter class . How can I do that? Is there any way that I can use onNext method?

I am beginner in Android rx-java and Retrofit .

Edit-1

I am using staggeredGridView to show the data. So, In my MainActivity class I am calling following code:

 StaggeredGridAdapter adapter = new StaggeredGridAdapter(this);
 mRecyclerView.setAdapter(adapter);

To fill the data in StaggeredGridView holder I have to call getWarehouse method.

Edit-2

MainActivity's onCreate() method:

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

    mToolbar = (Toolbar) findViewById(R.id.toolbar);
    getWarehouse();
    mRecyclerView = (RecyclerView) findViewById(R.id.staggering_grid);
    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));

    StaggeredGridAdapter adapter = new StaggeredGridAdapter(this);
    mRecyclerView.setAdapter(adapter);
    GridItemSpaces decoration = new GridItemSpaces(10);
    mRecyclerView.addItemDecoration(decoration);

}

Where StaggeredGridAdapter is:

public class StaggeredGridAdapter extends RecyclerView.Adapter<StaggeredGridAdapter.StaggeredGridView>{}

Edit-3

After the suggestion I call getWarehouse(); in MainActivity.onCreate method and copy the definition of getWarehouse() to MainActivity.class .

Also my MainActivity.getWarehouse.onNext method:

@Override
public void onNext(List<Warehouse> response) {
  mAdapter.addItems(response);
}

Where as mAdapter is private StaggeredGridAdapter mAdapter; which is initialized later in MainActivity.onCreate method.

What would be the definition of addItems method in StaggeredGridAdapter class?

Edit-4

Full definition of StaggeredGridAdapter

public class StaggeredGridAdapter extends RecyclerView.Adapter<StaggeredGridAdapter.StaggeredGridView> {
private Context context;
private List<Warehouse> warehouses = new ArrayList<Warehouse>();
int size;

public StaggeredGridAdapter(Context context) {
    this.context = context;
}

public void addItems(List<Warehouse> response){
    size = response.size();
    warehouses = response;
}

@Override
public StaggeredGridView onCreateViewHolder(ViewGroup parent, int viewType) {
    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
    StaggeredGridView staggeredGridView = new StaggeredGridView(layoutView);
    return staggeredGridView;
}

@Override
public void onBindViewHolder(StaggeredGridView holder, int position) {
    holder.textView.setText(warehouses.get(position).getFace());
}

@Override
public int getItemCount() {
    return size;
}

class StaggeredGridView extends RecyclerView.ViewHolder {
    TextView textView;

    public StaggeredGridView(View itemView) {
        super(itemView);

        textView = (TextView) itemView.findViewById(R.id.img_name);

    }
}

Rather than subscribing within the getWarehouse method, have getWarehouse return the observable and do the subscribe part in the adapter. This way you can have the onNext callback exist in the adapter and not in the calling method. Ideally you should instantiate the restadapter only once rather than everytime within the getWarehouse method as well.

public Observable<Warehouse> getWarehouse(){

adapter.getWarehouse()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread());

}

from adapter do this: someClass.getWarehouse().subscribe(new Subscriber()....)

I would leave the getWarehouse() in the Activity . In the same Activity you can keep a reference to StaggeredGridAdapter as you did with mRecyclerView. Create a public void addItems(List<Warehouse> response) in your Adapter, and when onNext is called you simply do mAdapter.addItems(response)

Eg

 public void addItems(List<Warehouse> items) {
     int oldSize = mDataSet.size();
     synchronized(mDataSet) {
         mDataSet.addAll(items);
     }
     notifyItemRangeInserted(oldSize - 1, mDataSet.size() - 1);
 }

where I am assuming that mDataSet is the name of the Collection you are using in your Adapter (your dataset).

I would also avoid to instantiate

   RestAdapter adapter = new  RestAdapter.Builder ()
            .setEndpoint(URL)
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .build();

everytime you call getWarehouse(); . subscribe returns a Subscription object. Keep it as member variable and call unsubscribe in your ondDestroy

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mSubscription != null) {
        mSubscription.unsubscribe();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM