androidandroid-recyclerviewgridviewdialogbaseadapter

BaseAdapter's Custom dialog recycler view not updating andorid


I do have a grid view implemented with base adapter. In each view there is a click listener. When we click on that, a Custom Dialog will open. In that dialog there is a Recycler view. That is updating each 10 seconds with the help of timer. That's updating perfectly. But when the custom dialog is opened and wait for next 10 sec to update the recycler view will not update the recycler view. But when i dismiss that dialog and immediately reopened then it will show updated recycler view.

RV is not updating when Custom dialog poped up

I want to update recycler view while the custom dialog poped up.

Git: https://github.com/jishnunkrishnan/baseadaptersample

Here is the code:

MainActivity.java:

package com.aijishnu.baseadaptersample;

import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.aijishnu.baseadaptersample.databinding.ActivityMainBinding;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;
    int i = 0;
    Context c;
    ArrayList<String> alNames;
    int[] arrayImages;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        c = this;
        arrayImages = new int[] {
                R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground,
                R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground,
                R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground
        };

        alNames = new ArrayList<>();
        for (int i=0;i<5; i++) {
            alNames.add("Raju: " + i);
        }
        updateData();

        Timer t = new Timer();
        t.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

                MainActivity.this.runOnUiThread(new Runnable() {
                    public void run() {

                        for (int i=0;i<5; i++) {
                            alNames.add("Raju Radha: " + i);
                        }
                        updateData();
                        Toast.makeText(c, i + " times", Toast.LENGTH_SHORT).show();
                    }
                });
                i++;
            }
        },15000,10000);
    }

    private void updateData() {

        MyAdapter adapter = new MyAdapter(this, arrayImages, alNames);
        binding.gvImages.setAdapter(adapter);
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <GridView
            android:id="@+id/gvImages"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:horizontalSpacing="10dp"
            android:verticalSpacing="10dp"
            android:numColumns="3"
            android:gravity="center"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

MyAdaper.java:

package com.aijishnu.baseadaptersample;

import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.aijishnu.baseadaptersample.databinding.CustomDesignBinding;
import java.util.ArrayList;

public class MyAdapter extends BaseAdapter {

    Context context;
    int[] arrayImages;
    DataAdapter dataAdapter;
    ArrayList<String> alNames;
    LayoutInflater mInflater;
    private boolean isDVisible = false;

    MyAdapter(Context context, int[] arrayImages, ArrayList<String> alNames) {

        mInflater = LayoutInflater.from(context);
        this.context = context;
        this.arrayImages = arrayImages;
        this.alNames = alNames;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {

            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.grid_layout, null);
        }
        ImageView imageView = convertView.findViewById(R.id.imageView);
        imageView.setImageResource(arrayImages[position]);

        if (isDVisible) {
            dataAdapter.notifyDataSetChanged();
        }

        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Dialog d = new Dialog(context);
                isDVisible = true;
                CustomDesignBinding binding = CustomDesignBinding.inflate(mInflater);
                d.setContentView(binding.getRoot());
                Window window = d.getWindow();
                assert window != null;
                window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

                binding.rvData.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL,false));
                dataAdapter = new DataAdapter(alNames);
                binding.rvData.setAdapter(dataAdapter);
                dataAdapter.notifyDataSetChanged();

                d.show();
            }
        });
        return convertView;
    }

    @Override
    public int getCount() {
        return arrayImages.length;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }
}

DataAdapter.java

package com.aijishnu.baseadaptersample;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.aijishnu.baseadaptersample.databinding.DesignBinding;
import java.util.ArrayList;

public class DataAdapter extends RecyclerView.Adapter<DataAdapter.Holder> {

    private ArrayList<String> alNames;
    public DataAdapter(ArrayList<String> names) {

        this.alNames = names;
    }

    static class Holder extends RecyclerView.ViewHolder {

        private final DesignBinding binding;

        public Holder (DesignBinding binding) {
            super(binding.getRoot());

            this.binding = binding;
        }
    }

    @NonNull
    @Override
    public DataAdapter.Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        return new DataAdapter.Holder(DesignBinding.inflate(LayoutInflater.from(parent.getContext()), parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull DataAdapter.Holder holder, int position) {

        holder.binding.tvName.setText(alNames.get(position));
    }

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

grid_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        tools:srcCompat="@tools:sample/avatars" />
</LinearLayout>

design.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tvName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

custom_desgin.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Solution

  • You should update the adapter of the dialog in the timer callback like this:

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
        ActivityMainBinding binding;
        int counter = 0;
        Context c;
        ArrayList<String> alNames;
        int[] arrayImages;
        MyAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
            c = this;
    
            setupData();
            setupAdapter();
    
            Timer t = new Timer();
            t.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    MainActivity.this.runOnUiThread(() -> {
                        ArrayList<String> newItems = new ArrayList<>();
                        for (int i = 0; i < 5; i++) {
                            newItems.add("Raju Radha: " + ++counter);
                        }
                        updateData(newItems);
                        Toast.makeText(c, counter + " times", Toast.LENGTH_SHORT).show();
                    });
                }
            }, 15000, 10000);
        }
    
        private void setupAdapter() {
            adapter = new MyAdapter(this, arrayImages, alNames);
            binding.gvImages.setAdapter(adapter);
        }
    
        private void setupData() {
            arrayImages = new int[]{
                    R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground,
                    R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground,
                    R.drawable.ic_launcher_background, R.drawable.ic_launcher_foreground
            };
    
            alNames = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                alNames.add("Raju: " + i);
            }
        }
    
        private void updateData(ArrayList<String> newItems) {
            adapter.addItem(newItems);
        }
    }
    

    MyAdapter.java

    public class MyAdapter extends BaseAdapter {
        Context context;
        int[] arrayImages;
        DataAdapter dataAdapter;
        ArrayList<String> alNames;
        LayoutInflater mInflater;
        Dialog d;
    
        MyAdapter(Context context, int[] arrayImages, ArrayList<String> alNames) {
            mInflater = LayoutInflater.from(context);
            this.context = context;
            this.arrayImages = arrayImages;
            this.alNames = alNames;
            d = new Dialog(context);
            dataAdapter = new DataAdapter(alNames);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.grid_layout, null);
            }
            ImageView imageView = convertView.findViewById(R.id.imageView);
            imageView.setImageResource(arrayImages[position]);
    
            convertView.setOnClickListener(v -> {
                CustomDesignBinding binding = CustomDesignBinding.inflate(mInflater);
                d.setContentView(binding.getRoot());
                Window window = d.getWindow();
                assert window != null;
                window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                binding.rvData.setLayoutManager(new LinearLayoutManager(context,
                        LinearLayoutManager.VERTICAL, false));
                binding.rvData.setAdapter(dataAdapter);
                d.show();
            });
            return convertView;
        }
    
        @Override
        public int getCount() {
            return arrayImages.length;
        }
    
        @Override
        public Object getItem(int position) {
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        public void addItem(ArrayList<String> items) {
            this.dataAdapter.addItems(items);
        }
    }
    

    DataAdapter.java

    public class DataAdapter extends RecyclerView.Adapter<DataAdapter.Holder> {
        private final ArrayList<String> alNames;
    
        public DataAdapter(ArrayList<String> names) {
            this.alNames = names;
        }
    
        public void addItems(ArrayList<String> items) {
            this.alNames.addAll(items);
            notifyDataSetChanged();
        }
    
        static class Holder extends RecyclerView.ViewHolder {
            private final DesignBinding binding;
    
            public Holder(DesignBinding binding) {
                super(binding.getRoot());
                this.binding = binding;
            }
        }
    
        @NonNull
        @Override
        public DataAdapter.Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new DataAdapter.Holder(DesignBinding.inflate(LayoutInflater.from(parent.getContext()),
                    parent, false));
        }
    
        @Override
        public void onBindViewHolder(@NonNull DataAdapter.Holder holder, int position) {
            holder.binding.tvName.setText(alNames.get(position));
        }
    
        @Override
        public int getItemCount() {
            return alNames.size();
        }
    

    Also, I recommend reusing your objects when possible.