【问题标题】:How to pass values from RecycleAdapter to MainActivity or Other Activities如何将值从 RecycleAdapter 传递到 MainActivity 或其他活动
【发布时间】:2016-01-26 07:37:31
【问题描述】:

我正在开发一个购物车应用程序,商品显示如下。有一个加号、减号 (+/-) 按钮可以选择数量。

如果产品数量发生变化,我需要将“产品名称”和“数量”传递给主要活动,以便我可以使用它们来准备最终购物车。我得到了一些使用数据库或一些内容提供者的建议,

我不知道该怎么做..请帮忙

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));
        }

    }
}

如何做到这一点,

【问题讨论】:

  • 您可以使用Helper Class

标签: android android-recyclerview


【解决方案1】:

你应该创建接口,activity实现了这个接口。

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

当你创建适配器时(最后一个参数就是这个接口)

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
}

// 在适配器中

  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());
    }

【讨论】:

    【解决方案2】:

    我在使用接口和观察者模式时都失败了。但是本地广播对我有用。

    在适配器中

    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);
    

    主要活动

    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();
            }
        };
    

    【讨论】:

    • 让我开心。感谢救生员
    • 也在 Kotlin 中工作过(使用 Android Studio 自动转换器)。
    • 我在 SO 中使用此代码解决我的问题,它可以正常工作,只是我需要做一些更改。
    【解决方案3】:

    解决这个问题的三种流行方法

    1. 接口

    Phuoc Huynh 已经解释了如何使用接口来解决这个问题。

    1. 观察者模式。

    尝试在观察者周围搜索以了解其工作原理。我们将使用他们想要接收的事件类型注册想要接收事件的类。将有一个管理器类来管理接收器的注册和注销,并将事件发送给所有接收器

    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);
                }
            }
        }
    }
    

    您的 MainActivity 将自己注册为递增和递减事件的接收者,并实现 IEventListener 的 onEvent 方法

    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)
        }
    }
    

    在你的适配器类中发送事件

    EventManager.getInstance().sendEvent("increment");
    EventManager.getInstance().sendEvent("decrement");
    
    1. 本地广播

    LocalBroadcasts 的工作方式与上述示例相同。您已经获得 LocalBroadcastManger 的实例并在其上发送广播。在 Activity 的 onCreate 中定义一个广播接收器,并在 Activity 中使用 registerReceiver() 进行注册。在注册接收器中传递一个意图过滤器,其动作类型与您希望活动接收的广播相同。确保在不需要广播时或在活动的 onDestroy 中取消注册广播

    【讨论】:

    • 是的,你能展示一些代码,如何实现它们
    【解决方案4】:

    看看这个。它对我有用。

    只需粘贴到您的活动或片段中

    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);
                        }
                    });
    

    【讨论】:

      【解决方案5】:
      //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 :)
      

      【讨论】:

      • 这不是开始一个新的活动吗?如果我想向当前正在运行的活动传递消息怎么办?
      【解决方案6】:

      在onBindViewHolder中添加这些代码

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

      添加到 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"));
      

      【讨论】:

        【解决方案7】:

        使用接口的简单解决方案:

        1. 使用包含对象/数据作为参数的方法创建接口

          public interface RecyclerViewDataPass {
              public void pass(String productName, String quantity);
          }
          
        2. Activity中实现接口方法并通过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. 编辑适配器的构造函数:

          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. RecyclerView Adapter 内部调用pass函数将数据发送到activity:

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

        【讨论】:

        • 完美。正是我想要的,详细的例子使它很容易适应。比使用 Intents (IMHO) 和一个非常容易理解的例子要好得多。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多