3

I'm retrieving some data from Firebase and showing it using RecyclerView.

My RecyclerView has cards in it in which the text and images are getting retrieved.

The card has a button on it which starts a floaty. The floaty has a ImageView and a TextView in which the image and text from the card from which the button was clicked should be shown.

The problem is that when clicking that button of the first card, the floaty is getting started and showing the image and text from that respective card, but when I press the button of another cards to start the floaty, floaty starts but the image and text from the respective card is not shown in it.

Here's my code:

@Override
    public void bindView(final ViewHolder holder) {
        super.bindView(holder);

       holder.progressBar.findViewById(R.id.progressBar_loading_image);
        holder.imageUID.setText(imageUIDh);
        holder.hDescription.setText(hDescription);

        if (imageUIDh != null) {

            holder.progressBar.setVisibility(View.VISIBLE);

            if (imageUIDh.startsWith("https://firebasestorage.googleapis.com/") || imageUIDh.startsWith("content://")) {
                Picasso.with(holder.itemView.getContext()).cancelRequest(holder.homelessImage);
                Picasso.with(holder.itemView.getContext())
                        .load(imageUIDh)
                        .error(R.drawable.ic_warning_black_24dp)
                        .into(holder.homelessImage, new Callback() {
                    @Override
                    public void onSuccess() {
                        holder.progressBar.setVisibility(View.INVISIBLE);
                    }

                    @Override
                    public void onError() {
                        // TODO Auto-generated method stub
                        Toast.makeText(holder.itemView.getContext(), "Error occurred while loading images. Please retry.", Toast.LENGTH_SHORT).show();
                    }
                });



                final View head = LayoutInflater.from(holder.itemView.getContext()).inflate(R.layout.widget_chathead, null);

                final View body = LayoutInflater.from(holder.itemView.getContext()).inflate(R.layout.content_help_request_chat_head, null);

                holder.progressBar2 = (ProgressBar) body.findViewById(R.id.progressBar_loading_image_ch);
                final ImageView hImageInFloaty = (ImageView) body.findViewById(R.id.hImageHF);
                final TextView hDescriptionInFloaty = (TextView) body.findViewById(R.id.hDescriptionHF);

                holder.btn_accept = (Button) holder.itemView.findViewById(R.id.btn_accept);
                holder.btn_accept.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                        if (holder.isNetworkAvailable()) {
                            AlertDialog.Builder builder = new AlertDialog.Builder(holder.itemView.getContext());
                            builder.setMessage(R.string.request_accepted_txt);
                            builder.setPositiveButton("Yes button", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {

                                            holder.floaty = Floaty.createInstance(holder.itemView.getContext(), head, body, holder.NOTIFICATION_ID, notification);
                                            holder.floaty.startService();
                                            hDescriptionInFloaty.setText(holder.hDescription.getText().toString());
                                            Picasso.with(holder.itemView.getContext())
                                                    .load(imageUIDh)
                                                    .error(R.drawable.ic_warning_black_24dp)
                                                    .into(hImageInFloaty, new Callback() {
                                                        @Override
                                                        public void onSuccess() {
                                                            holder.progressBar2.setVisibility(View.GONE);
                                                        }

                                                        @Override
                                                        public void onError() {
                                                            // TODO Auto-generated method stub

                                                        }
                                                    });

                                }

                            });
                            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    Toast.makeText(holder.itemView.getContext(), "The help-request has been rejected.", Toast.LENGTH_LONG).show();
                                }
                            });
                            AlertDialog dialog = builder.create();
                            dialog.show();
                        } else {
                            android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(holder.itemView.getContext());
                            builder.setTitle("No internet connection!");
                            builder.setMessage("We need internet connection to navigate you more accurately. Please connect to the internet and then accept the help-request.");
                            builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    Intent intent = new Intent(Settings.ACTION_SETTINGS);
                                    holder.itemView.getContext().startActivity(intent);
                                }
                            });
                            builder.setNegativeButton("Cancel", null);
                            builder.show();
                        }

                    }
                });

    }

As floaties need permission, I'm populating recyclerview after getting the permission (for Android M and above only). Here's the code:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            startFloatyForAboveAndroidL();
        }

Here's startFloatyForAboveAndroidL():

@TargetApi(Build.VERSION_CODES.M)
    public void startFloatyForAboveAndroidL() {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivityForResult(intent, PERMISSION_REQUEST_CODE);
        } else {
            recyclerView.setAdapter(fastItemAdapter);
        }
    }

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == REQUEST_CODE){
            mSheetLayout.contractFab();
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (requestCode == PERMISSION_REQUEST_CODE) {
                if (Settings.canDrawOverlays(this)) {
                    recyclerView.setAdapter(fastItemAdapter);
                } else {
                    Spanned message = Html.fromHtml("Please allow this permission, so <b>Floaties</b> could be drawn.");
                    Toast.makeText(this, message, Toast.LENGTH_LONG).show();
                }
            }
        }
    }

code after trying Eric's answer:--

protected static class ViewHolder extends RecyclerView.ViewHolder {

        ImageView hImage;
        TextView imageUID, hDescription;
        View head, body;
        Floaty floaty;
        TextView hDescroptionInFloaty;
        ImageView hImageInFloaty;
        Notification notification;
        Button btn_accept;
        ProgressBar progressBar, progressBar2;
        AppCompatButton btnCloseFloaty;
        private static final int NOTIFICATION_ID = 1500;

        public ViewHolder(final View itemView) {
            super(itemView);

            Intent intent = new Intent(itemView.getContext(), HelpRequest.class);
            PendingIntent resultPendingIntent = PendingIntent.getActivity(itemView.getContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            notification = Floaty.createNotification(itemView.getContext(), "HumaneHelper", "Floaty has started with homeless's pic and description", R.mipmap.ic_launcher, resultPendingIntent);

            head = LayoutInflater.from(itemView.getContext()).inflate(R.layout.widget_chathead, null);
            // You should not add click listeners to head as it will be overridden, but the purpose of not making head just
            // an ImageView is so you can add multiple views in it, and show and hide the relevant views to notify user etc.
            body = LayoutInflater.from(itemView.getContext()).inflate(R.layout.content_help_request_chat_head, null);

            floaty = Floaty.createInstance(itemView.getContext(), head, body, NOTIFICATION_ID, notification);

            btnCloseFloaty = (AppCompatButton) body.findViewById(R.id.btn_close_floaty);
            btnCloseFloaty.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    floaty.stopService();
                }
            });

            hDescroptionInFloaty = (TextView) body.findViewById(R.id.hDescriptionHF);
            hImageInFloaty = (ImageView) body.findViewById(R.id.hImageHF);

    }

here's bindView():

    @Override
        public void bindView(final ViewHolder holder) {
            super.bindView(holder);
    holder.imageUID.setText(imageUIDh);
            holder.hDescription.setText(hDescription);

    if (imageUIDh != null) {

                    holder.progressBar2 = (ProgressBar) holder.body.findViewById(R.id.progressBar_loading_image_ch);

                    holder.btn_accept = (Button) holder.itemView.findViewById(R.id.btn_accept);
   View.OnClickListener() {
                        @Override
                        public void onClick(View view) {

                            if (holder.isNetworkAvailable()) {

                                holder.hDescroptionInFloaty.setText(holder.hDescription.getText().toString());
                                Picasso.with(holder.itemView.getContext())
                                        .load(imageUIDh)
                                        .error(R.drawable.ic_warning_black_24dp)
                                        .into(holder.hImageInFloaty, new Callback() {
                                            @Override
                                            public void onSuccess() {
                                                holder.progressBar2.setVisibility(View.GONE);
                                            }

                                            @Override
                                            public void onError() {
                                                // TODO Auto-generated method stub

                                            }
                                        });
                                Toast.makeText(holder.itemView.getContext(), "updated: " + holder.homelessDescroptionInFloaty.getText(), Toast.LENGTH_LONG).show();

                                AlertDialog.Builder builder = new AlertDialog.Builder(holder.itemView.getContext());
                                builder.setMessage(R.string.request_accepted_txt);
                                builder.setPositiveButton("Navigate me", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {

                                                holder.floaty = Floaty.createInstance(holder.itemView.getContext(), holder.head, holder.body, holder.NOTIFICATION_ID, holder.notification);
                                                holder.floaty.startService();

                                    }

                                });
                                builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {
                                        Toast.makeText(holder.itemView.getContext(), "The help-request has been rejected.", Toast.LENGTH_LONG).show();
                                    }
                                });
                                AlertDialog dialog = builder.create();
                                dialog.show();
                            } else {
                                android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(holder.itemView.getContext());
                                builder.setTitle("No internet connection!");
                                builder.setMessage("We need internet connection to navigate you more accurately. Please connect to the internet and then accept the help-request.");
                                builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {
                                        Intent intent = new Intent(Settings.ACTION_SETTINGS);
                                        holder.itemView.getContext().startActivity(intent);
                                    }
                                });
                                builder.setNegativeButton("Cancel", null);
                                builder.show();
                            }

                        }
                    });

                } else {
                    Toast.makeText(holder.itemView.getContext(), "some problem", Toast.LENGTH_SHORT).show();
                }
        }

What is happening wrong here? How can I get the text and image from the card of whose button was clicked into the floaty?

Hammad Nasir
  • 2,889
  • 7
  • 52
  • 133
  • 1
    I guess you create Floaty object when you create Holder. Android can reuse holders toshow different items. You should obtain data and create Floaty in onClick. – babay Jun 25 '16 at 03:14
  • awesome. thanks for the clue. this did the job here for me! :) – Hammad Nasir Jun 25 '16 at 05:55
  • can you have a look at this too: http://stackoverflow.com/questions/38023511/how-to-place-ads-randomly-in-between-of-recyclerview-please-see-details Please?... – Hammad Nasir Jun 25 '16 at 06:05
  • hey @babay everything went fine but then again all of a sudden the problem reoccured. Please take another look, maybe you get the problem again. Thanks. – Hammad Nasir Jun 25 '16 at 18:01
  • I have noticed something that now the problem is that the textview and imageview in floaty is getting set one time and is not getting updated. – Hammad Nasir Jun 25 '16 at 18:14
  • please reply @babay sir... – Hammad Nasir Jun 26 '16 at 01:38
  • it is very difficult to read you code - it is very noodle-like. can you please rewrite it to make it less nested? separate methods, callback objects with ass little nesting as possible. It would be much easier to read you code. Declaring callback code inside callback code is bad practice. Moreover, I even don't understand, where is all this code happens. What method is it in? – babay Jun 26 '16 at 01:44
  • @babay is the code clear now? sorry for disturbance. – Hammad Nasir Jun 26 '16 at 01:57
  • nope. new View.OnClickListener inside View.OnClickListener - it is not good. I'll try to rewrite it. moreover, line 3: holder.progressBar.findViewById(R.id.progressBar_loading_image); does nothing at all. it only finds a view, nothing more. – babay Jun 26 '16 at 02:05
  • @babay I would like to get on main purpose of the question, bro. Please help with that! – Hammad Nasir Jun 26 '16 at 02:08
  • @babay I have updated some more code pls have a look.. – Hammad Nasir Jun 26 '16 at 02:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/115639/discussion-between-hammad-nasir-and-babay). – Hammad Nasir Jun 26 '16 at 13:03

2 Answers2

1

If you take a look at the Floaty code here. You will notice it uses SingletonPattern. Hence that is the reason it works for the first time but after that, it shows incorrect data. One solution that comes is to extend the Floaty class, and add your own createInstance method. The body of method would be something like this:

public static synchronized Floaty createInstance(Context context, View head, View body, int notificationId, Notification notification, FloatyOrientationListener
        floatyOrientationListener) {
    if (floaty == null) {
        floaty = new Floaty(context, head, body, notificationId, notification, floatyOrientationListener);
    }else {
        floaty.stopService();
        floaty = null;
        floaty = new Floaty(context, head, body, notificationId, notification, floatyOrientationListener);
    }
    return floaty;
}

I hope this works.

Approach 2

Another simpler, approach that comes to mind is, you initialize the Floaty only once. Then just get reference to the body in your holder and modify the ImageView and the TextView from your holder.

Eric B.
  • 4,622
  • 2
  • 18
  • 33
  • hey, approach 2 didn't worked! How to use approach 1? – Hammad Nasir Jun 26 '16 at 10:22
  • no error but same problem... I did this with my adapter: `fastItemAdapter.add(0, helpRequest); recyclerView.setAdapter(fastItemAdapter); recyclerView.smoothScrollToPosition(0);` can this cause problem? – Hammad Nasir Jun 26 '16 at 10:52
  • Why are you keeping access to the Floaty in the holder? Once the create instance method is called, you can access the Floaty any where using the `Floaty#getInstance()` method. – Eric B. Jun 26 '16 at 10:56
  • this is just not happening, bro!! This is just frustrating me so much :( Please tell me from scratch how can I achieve this??? – Hammad Nasir Jun 26 '16 at 11:13
  • 1
    I will code a demo project with recycler view and upload it in github. Give me a day or two. – Eric B. Jun 26 '16 at 11:29
  • bro... i don't have a day or two.... google admob student app challenge's last date is june 28 and I have to submit app before that. – Hammad Nasir Jun 26 '16 at 11:31
  • 1
    Ok i will do it later tonight – Eric B. Jun 26 '16 at 11:35
  • okay tell me how can I edit `Floaty.java` and use the edited one in my project? – Hammad Nasir Jun 26 '16 at 11:41
  • Create a class say `MyFloaty` and make it extend the `Floaty` class. – Eric B. Jun 26 '16 at 11:43
  • THANKS.. please tell how can I get rid of these errors too: `'x' has private access in 'com.bezyapps.floaties.library.Floaty'`? – Hammad Nasir Jun 26 '16 at 12:29
  • You can't. They have private access. You can do another thing, import floaties as a library project and then modify the library core itself. – Eric B. Jun 26 '16 at 12:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/115656/discussion-between-hammad-nasir-and-eric-b). – Hammad Nasir Jun 26 '16 at 18:09
0

I've tryed to rewrite your code.

  1. I don't know class of imageUIDh, but I guess it's string.

  2. imageUIDh is not defined in your code, so I don't know where do you get in from. But I've added field imageUIDh to your ViewHolder. You should update it on every bindView.

  3. some lines should be moved to ViewHolder's constructor

  4. I've added ViewHolder as a tag to btn_accept, so you can use one clickListener for all the ViewHolders.

  5. now there are much less nesting in code - it is much easier to read, debug and to find issues. may be the issue is now solved

        @Override
        public void bindView(final ViewHolder holder) {
            super.bindView(holder);
    
            holder.progressBar.findViewById(R.id.progressBar_loading_image);
            holder.imageUID.setText(imageUIDh);
            holder.imageUIDh = imageUIDh;
            holder.hDescription.setText(hDescription);
    
            /// THESE 2 LINES SHOULD BE DONE IN HOLDER'S CONSTRUCTOR!!!!!
            holder.btn_accept = (Button) holder.itemView.findViewById(R.id.btn_accept);
            holder.btn_accept.setTag(holder);
    
            if (imageUIDh != null) {
                holder.progressBar.setVisibility(View.VISIBLE);
    
                if (imageUIDh.startsWith("https://firebasestorage.googleapis.com/") || imageUIDh.startsWith("content://")) {
                    doSomethingWithPicaso(imageUIDh, holder.homelessImage);
    
                    /*
                    /// THESE LINES ARE BE MOVED INTO onClick()
                    final View head = LayoutInflater.from(holder.itemView.getContext()).inflate(R.layout.widget_chathead, null);
                    final View body = LayoutInflater.from(holder.itemView.getContext()).inflate(R.layout.content_help_request_chat_head, null);
    
                    final ImageView hImageInFloaty = (ImageView) body.findViewById(R.id.hImageHF);
                    final TextView hDescriptionInFloaty = (TextView) body.findViewById(R.id.hDescriptionHF);
                    */
    
                    holder.btn_accept.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ViewHolder holder = (ViewHolder) view.getTag();
                            if (holder.isNetworkAvailable()) {
                                showOnNetworkAvailableAlertDialog(view.getContext(), holder.imageUIDh, holder.hDescription.getText().toString());
                            } else {
                               showNoNetworkAlert(view.getContext());
                            }
                        }
                    });
                }
            }
        }
    
        private void doSomethingWithPicaso(String imageUIDh, ImageView target, final HolderView holder){
            final Context context = target.getContext();
            Picasso.with(context).cancelRequest(holder.homelessImage);
            Picasso.with(context)
                    .load(imageUIDh)
                    .error(R.drawable.ic_warning_black_24dp)
                    .into(target, new Callback() {
                        @Override
                        public void onSuccess() {
                            holder.progressBar.setVisibility(View.INVISIBLE);
                        }
    
                        @Override
                        public void onError() {
                            Toast.makeText(context, "Error occurred while loading images. Please retry.", Toast.LENGTH_SHORT).show();
                        }
                    });
        }
    
        private void showOnNetworkAvailableAlertDialog(final Context context, final String imageUIDh, final String descriptionText){
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(R.string.request_accepted_txt);
            builder.setPositiveButton("Yes button", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
    
                    final View head = LayoutInflater.from(context).inflate(R.layout.widget_chathead, null);
                    final View body = LayoutInflater.from(context).inflate(R.layout.content_help_request_chat_head, null);
    
                    final ImageView hImageInFloaty = (ImageView) body.findViewById(R.id.hImageHF);
                    final TextView hDescriptionInFloaty = (TextView) body.findViewById(R.id.hDescriptionHF);
                    final View progressBar = body.findViewById(R.id.progressBar_loading_image_ch);
    
                    holder.floaty = Floaty.createInstance(context, head, body, holder.NOTIFICATION_ID, notification);
                    holder.floaty.startService();
                    hDescriptionInFloaty.setText(descriptionText);
                    Picasso.with(context)
                            .load(imageUIDh)
                            .error(R.drawable.ic_warning_black_24dp)
                            .into(hImageInFloaty, new Callback() {
                                @Override
                                public void onSuccess() {
                                    progressBar.setVisibility(View.GONE);
                                }
    
                                @Override
                                public void onError() {
                                    // TODO Auto-generated method stub
    
                                }
                            });
    
                }
    
            });
            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    Toast.makeText(holder.itemView.getContext(), "The help-request has been rejected.", Toast.LENGTH_LONG).show();
                }
            });
            builder.show();
        }
    
        private void showNoNetworkAlert(final Context context){
            android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(context);
            builder.setTitle("No internet connection!");
            builder.setMessage("We need internet connection to navigate you more accurately. Please connect to the internet and then accept the help-request.");
            builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    Intent intent = new Intent(Settings.ACTION_SETTINGS);
                    context.startActivity(intent);
                }
            });
            builder.setNegativeButton("Cancel", null);
            builder.show();
        }
    
babay
  • 4,689
  • 1
  • 26
  • 40