Joseph Joseph
Joseph Joseph

Reputation: 859

How to pass values from RecycleAdapter to MainActivity or Other Activities

I am working on a shopping cart app,Items are displayed as below.There is a plus, minus (+/-) buttons to choose the number of quantity.

If product quantity is changed, I need to pass "productname" and "quantity" to the main activity so that I could use them to prepare final cart. I got some suggestions to use database or some content providers,

I am not sure how to do it.., please help

Recycle Adapter for Shoping cart

MainActivity.java

public class MainActivity extends AppCompatActivity {

RecyclerView recyclerView;
RecycleAdapter recycleAdapter;
List<HashMap<String, String>> onlineData;
ProgressDialog pd;

Toolbar toolbar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    recyclerView = (RecyclerView) findViewById(R.id.recyle_view);
    toolbar= (Toolbar) findViewById(R.id.anim_toolbar);
    setSupportActionBar(toolbar);

    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getBaseContext());
    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.setHasFixedSize(true);

    final String url = "http://www.qa4.org/?json=get_recent_posts&count=45";
    new AsyncHttpTask().execute(url);



}

public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

    @Override
    protected void onPreExecute() {
        pd=new ProgressDialog(MainActivity.this);
        pd.requestWindowFeature(Window.FEATURE_NO_TITLE);
        pd.setMessage("Loading please wait...");
        pd.setCancelable(false);
        pd.show();
    }

    @Override
    protected Integer doInBackground(String... params) {
        Integer result = 0;
        HttpURLConnection urlConnection;
        try {
            URL url = new URL(params[0]);
            urlConnection = (HttpURLConnection) url.openConnection();
            int statusCode = urlConnection.getResponseCode();

            // 200 represents HTTP OK
            if (statusCode == 200) {
                BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = r.readLine()) != null) {
                    response.append(line);
                }
                parseResult(response.toString());
                result = 1; // Successful
            } else {
                result = 0; //"Failed to fetch data!";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result; //"Failed to fetch data!";
    }

    @Override
    protected void onPostExecute(Integer result) {
        // Download complete. Let us update UI
        pd.dismiss();

        if (result == 1) {
            recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData);
            recyclerView.setAdapter(recycleAdapter);
        } else {
            Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
        }
    }
}

private void parseResult(String result) {
    try {
        JSONObject response = new JSONObject(result);
        JSONArray posts = response.optJSONArray("posts");
        onlineData = new ArrayList<>();

        for (int i = 0; i < posts.length(); i++) {
            JSONObject post = posts.optJSONObject(i);

            HashMap<String, String> item = new HashMap<>();
            item.put("title", post.optString("title"));

            JSONArray jsonArray = post.getJSONArray("attachments");
            JSONObject jsonObject1 = jsonArray.getJSONObject(0);
            JSONObject jsonArrayImages = jsonObject1.getJSONObject("images");
            JSONObject jsonArrayThumb = jsonArrayImages.getJSONObject("thumbnail");

            item.put("thump", jsonArrayThumb.optString("url"));

            onlineData.add(item);


        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

}

RecycleAdapter.java

public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolderRec> {

    List<HashMap<String, String>> onlineData;
    SQLiteDatabase db;
    Context context;
    RecycleAdapter(Context context,List<HashMap<String, String>> onlineData){
        this.onlineData = onlineData;
        this.context=context;
    }

    @Override
    public ViewHolderRec onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolderRec( LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycle, parent, false));

       }

    @Override
    public void onBindViewHolder(ViewHolderRec holder, int position) {

    HashMap<String,String> map =onlineData.get(position);

        //Download image using picasso library
        Picasso.with(context).load(map.get("thump"))
                .error(R.drawable.placeholder)
                .placeholder(R.drawable.placeholder)
                .into(holder.iv);

        holder.tv.setText(map.get("title"));

    }

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

    public class ViewHolderRec extends RecyclerView.ViewHolder implements View.OnClickListener{
        ImageView iv;
        TextView tv, quantity;
        ImageView Add_Cart;
        ImageView Remove_Cart;

        public ViewHolderRec(View itemView) {
            super(itemView);
            iv = (ImageView) itemView.findViewById(R.id.thumbnail);
            tv = (TextView) itemView.findViewById(R.id.title);
            quantity = (TextView)itemView.findViewById(R.id.cart_qty);
            Add_Cart = (ImageView)itemView.findViewById(R.id.cart_add);
            Remove_Cart = (ImageView)itemView.findViewById(R.id.cart_remove);
            itemView.setOnClickListener(this);
            Add_Cart.setOnClickListener(this);
            Remove_Cart.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if(v.getId() == Add_Cart.getId()){
                 increment();
            }
            else if(v.getId() == Remove_Cart.getId()){
                decrement();
            }
        }

        public void increment(){
            int currentNos = Integer.parseInt(quantity.getText().toString()) ;
           quantity.setText(String.valueOf(++currentNos));
        }

        public void decrement(){
            int currentNos = Integer.parseInt(quantity.getText().toString()) ;
            quantity.setText(String.valueOf(--currentNos));
        }

    }
}

How to do this,

Upvotes: 29

Views: 79062

Answers (7)

Amrk000
Amrk000

Reputation: 71

Simple solution using interface:

  1. Create an interface with method containing objects/data as parameters:

    public interface RecyclerViewDataPass {
        public void pass(String productName, String quantity);
    }
    
  2. Implement interface method in Activity & pass it through RecyclerView Adapter:

    RecyclerViewDataPass recyclerViewDataPass = new RecyclerViewDataPass() {
                @Override
                public void pass(String productName, String quantity) {
                //we get data from adapter here
                //assign parameters to activity variables or do the needed operations
                }
            };
    
    recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData,recyclerViewDataPass);
    recyclerView.setAdapter(recycleAdapter);
    
  3. Edit adapter's constructor:

    public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolderRec> {
    
        List<HashMap<String, String>> onlineData;
        SQLiteDatabase db;
        Context context;
        RecyclerViewDataPass recyclerViewDataPass; //here is our data pass object
    
        RecycleAdapter(Context context,List<HashMap<String, String>> onlineData, RecyclerViewDataPass recyclerViewDataPass){
            this.onlineData = onlineData;
            this.context=context;
            this.recyclerViewDataPass=recyclerViewDataPass; //get data pass object from activity
        }
    
  4. Inside RecyclerView Adapter call pass function to send data to activity:

    recyclerViewDataPass.pass(tv.getText().toString(), quantity.getText().toString());
    

Upvotes: 4

Ali Eslami
Ali Eslami

Reputation: 83

add these codes in onBindViewHolder

Intent intent = new Intent("message_subject_intent");
intent.putExtra("name" , String.valueOf(messageSubject.getname()));
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

Add on MainActivity

    public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
        String name= intent.getStringExtra("name");
        Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
        }
    };
    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,new IntentFilter("message_subject_intent"));

Upvotes: 1

Tousif Akram
Tousif Akram

Reputation: 149

//Simply it works for me
//In onBindViewHolder of RecyclerAdapter write the following code on clickEvent of any view;


Intent intent = new Intent(tContext, TargetActivity.class);
intent.putExtra("key", "value");
tContext.startActivity(intent);


//TargetActivity.java

  String str = getIntent().getStringExtra("key");
//You got the value as String :)

Upvotes: 1

Aasik
Aasik

Reputation: 11

Check out this. It works for me.

Just Paste in Your Activity or Fragment

rvSelectedProductList = Recyclerview
selcetedItemAdapter = RecyclerView Adapter
              rvSelectedProductList.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {

                        final int itemCount = selectedItemAdapter.getItemCount();

                        for (int i = 0; i < itemCount; i++) {
                            TextView tvSelling = rvSelectedProductList.getChildAt(i).findViewById(R.id.tvSelling);
                            TextView textViewDrawerTitle = rvSelectedProductList.getChildAt(i).findViewById(R.id.tvCartQty);


                            String totalamount = tvSelling.getText().toString();
                            String qty = textViewDrawerTitle.getText().toString();
                            System.out.println("qty" + qty);
                            System.out.println("total" + totalamount);
                        }
                        rvSelectedProductList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                });

Upvotes: 1

Phuoc Huynh
Phuoc Huynh

Reputation: 692

You should create interface, and activity implements this interface.

public interface OnItemClick {
    void onClick (String value);
}

When you create adapter (last parameter is this interface)

public class MainActivity extends AppCompatActivity implements OnItemClick {
 recycleAdapter = new RecycleAdapter(MainActivity.this,onlineData, this);
            recyclerView.setAdapter(recycleAdapter);

 @Override
 void onClick (String value){
// value this data you receive when increment() / decrement() called
}

// In Adapter

  private OnItemClick mCallback;

RecycleAdapter(Context context,List<HashMap<String, String>>     onlineData,OnItemClick listener){
    this.onlineData = onlineData;
    this.context = context;
    this.mCallback = listener;
 }
    ....

    public void increment(){
        int currentNos = Integer.parseInt(quantity.getText().toString()) ;
        quantity.setText(String.valueOf(++currentNos));
        mCallback.onClick(quantity.getText().toString());
    }

    public void decrement(){
        int currentNos = Integer.parseInt(quantity.getText().toString()) ;
        quantity.setText(String.valueOf(--currentNos));
        mCallback.onClick(quantity.getText().toString());
    }

Upvotes: 58

Joseph Joseph
Joseph Joseph

Reputation: 859

I failed to do it with both Interface and Observer pattern. But Local Broadcast worked for me.

In Adapter

String ItemName = tv.getText().toString();
                String qty = quantity.getText().toString();
                Intent intent = new Intent("custom-message");
                //            intent.putExtra("quantity",Integer.parseInt(quantity.getText().toString()));
                intent.putExtra("quantity",qty);
                intent.putExtra("item",ItemName);
                LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

Main Activity

public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-message".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-message"));
}

...
public BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Get extra data included in the Intent
            String ItemName = intent.getStringExtra("item");
            String qty = intent.getStringExtra("quantity");
             Toast.makeText(MainActivity.this,ItemName +" "+qty ,Toast.LENGTH_SHORT).show();
        }
    };

Upvotes: 45

Suhaib Roomy
Suhaib Roomy

Reputation: 2600

Three popular ways to solve this problem

  1. Interfaces

Phuoc Huynh has already explained how to use interfaces to solves this.

  1. Observer pattern.

Try googling around observer to understand how it works. We will register the classes who want to receive events with the type of events they want to receive. There will be a manager classes to manage registering and unregistering of receivers and also to send the events to all receivers

public class EventManager {
    private static EventManager eventManager;
    private static Object syncObject = new Object();
    private HashMap<String, ArrayList<EventListener>> listeners = new   HashMap<>();

    private EventManager(){}

    public static EventManager getInstance() {
        if (eventManager == null) {
            synchronized (syncObject) {
                if (eventManager == null) {
                    eventManager = new EventManager();
                }
            }
        }
        return eventManager;
    }

    public synchronized void registerListener(String event, EventListener listener) {
        if (listeners.containsKey(event)) {
            listeners.get(event).add(listener);
        } else {
            ArrayList<EventListener> arrayList = new ArrayList<>();
            arrayList.add(listener);
            listeners.put(event, arrayList);
        }
    }

    public synchronized void unRegisterListener(String event, EventListener listener) {
        if (listeners.containsKey(event)) {
            listeners.get(event).remove(listener);
            if (listeners.get(event).size() == 0) {
                listeners.remove(event);
            }
        }
    }

    public void sendEvent(String event, Object o) {
        if (listeners.containsKey(event)) {
            ArrayList<EventListener> listener = listeners.get(event);
            for (EventListener eventListener : listener) {
                eventListener.onEvent(o);
            }
        }
    }
}

Your MainActivity will register itself as a receiver of increment and decrement events and also implement onEvent method of IEventListener

public class MainActivity extends AppCompatActivity implements IEventListener{
    @Override
    protected void onCreate(Bundle onSavedInstanceState) {
        EventManager.getInstance().registerEvent("increment", this);
        EventManager.getInstance().registerEvent("decrement", this)
    }

    @Override
    public void onEvent(String event) {
        if (event.equals("increment") {
            //increment
        } else if (event.equals("decrement") {
            //decrement
        }
    }

    @Override
    protected void onDestroy() {
        EventManager.getInstance().unRegisterEvent("increment", this);
        EventManager.getInstance().unRegisterEvent("decrement", this)
    }
}

In you adapter class send the events

EventManager.getInstance().sendEvent("increment");
EventManager.getInstance().sendEvent("decrement");
  1. LocalBroadcasts

LocalBroadcasts works the same way as the above example. you have get Instance of LocalBroadcastManger and send Broadcast on it. Define a broadcast receiver in the onCreate of the activity and register it using registerReceiver() in the Activity. Pass an intent filter in the register receiver with actiontype same as the broadcasts you want your activity to receive. Make sure you unregister the broadcasts whenever you don't need them or in the onDestroy of the activity

Upvotes: 5

Related Questions