4

What is the preffered way of populating a RecyclerView and keeping track of data changes using ActiveAndroid ORM?

I've asked a question on this topic recently. But it got too verbose, and people are so lazy, that someone would scarcely read it till the end.

The very essence of it: Does somebody have a working example of RecyclerView populated from a database through ActiveAndroid?

Community
  • 1
  • 1
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259

3 Answers3

0

I had used this library once, but with a ListView. I think this code should work with the RecyclerView:

/* The database */
@Table(name = "Person")
public class Person extends Model {
    @Column(name = "Name")
    public String name;    
    @Column(name = "Age")
    public int age;
}


/* Your MainActivity */

List<Person> list = new ArrayList<>();
private RecyclerView rv;

/* Activity onCreate */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    list = getList(15);
    rv = (RecyclerView) findViewById(R.id.recycler_view);
    rv.setLayoutManager(new LinearLayoutManager(this));
    rv.setAdapter(new Adapter());

}

private List<Person> getList(int age){
    return new Select()
        .from(Person.class)
        .where("Age = ?", age)
        .orderBy(/* order you like */)
        .executeSingle();
}

private class Adapter extends RecyclerView.Adapter<Adapter.Holder> {

        @Override
        public Adapter onCreateViewHolder(ViewGroup parent, int viewType) {
            // you should inflate the layout you want be laid in every row of the recycler view. Im just inflating a text view for convinence
            return new Holder(LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false));
        }

        @Override
        public void onBindViewHolder(Holder holder, int position) {
            // assign values to all view in the holder.
            holder.tv.setText(list.get(position).name);
        }

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

        public class Holder extends RecyclerView.ViewHolder {
            // here you load all the view in your layout
            TextView tv;

            public Holder(View itemView) {
                super(itemView);
                tv = (TextView) itemView;
            }
        }
    }

Here, I am assuming that you've already created and stored values in the database, as the question ask only to populate from the database.

I haven't tested it, but I think it should work.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
hello_world
  • 778
  • 1
  • 10
  • 26
  • The question is not only about populating `RecyclerView` from database, but also about binding a view to a dataset and observing changes. So when changes occur on the dataset, the view is automatically notified about them. – naXa stands with Ukraine Jul 20 '15 at 21:07
0

A pattern could be used to implement this. Use BroadcastReceiver to notify your activity whenever the are changes to your database (just send an explicit intent to your activity and implement activity.onNewIntent()).

Use LocalBroadcastManager to sendBroadCast to your BroadCastReceiver when you finished add your changes to database. Hope this help.

Tin Tran
  • 2,265
  • 1
  • 14
  • 17
0

I use eventbus to notify my recyclerview's adapter whenever i add data to my database.

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private final String TAG = "MainActivity";
    private EditText etName, etAge;
    private Button btnAdd;
    private EventBus bus = EventBus.getDefault();

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

        //declare all views
        etName = (EditText) findViewById(R.id.et_name);
        etAge = (EditText) findViewById(R.id.et_age);
        btnAdd = (Button) findViewById(R.id.btn_add);

        //add onClickListener to button
        btnAdd.setOnClickListener(this);

        android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.frame_layout, ListFragment.newInstance());
        transaction.commit();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();

        switch (id) {
            case R.id.btn_add:
                PersonModel personModel = new PersonModel();

                if (isEmpty(etName) || isEmpty(etAge)) {
                    Toast.makeText(this, "Please fill in all details", Toast.LENGTH_LONG).show();
                } else {
                    personModel.name = etName.getText().toString();
                    personModel.age = etAge.getText().toString();

                    //Save data to database
                    personModel.save();

                    //Broadcast the event to notify fragment
                    bus.post("NOTIFY");
                }
                break;
            default:
                Log.e(TAG, "Invalid view ID");
                break;
        }
    }

    //Check edit text whether is empty or not
    private boolean isEmpty(EditText etText) {
        return etText.getText().toString().trim().length() == 0;
    }
}

PersonModel.java

@Table(name = "PersonModel")
public class PersonModel extends Model {
    @Column(name = "NAME")
    public String name;

    @Column(name = "AGE")
    public String age;
}

PersonAdapter.java

public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.MyViewHolder> {
    private Context mContext;
    private List<PersonModel> models;

    public PersonAdapter(Context context, List<PersonModel> models) {
        this.mContext = context;
        this.models = models;
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView name, age;

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

            name = (TextView) itemView.findViewById(R.id.name);
            age = (TextView) itemView.findViewById(R.id.age);
        }
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext).inflate(R.layout.person_cell, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        PersonModel personModel = models.get(position);

        holder.name.setText(personModel.name);
        holder.age.setText(personModel.age);
    }

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

ListFragment.java

public class ListFragment extends Fragment {
    private final String TAG = "ListFragment";
    private EventBus bus = EventBus.getDefault();
    private List<PersonModel> models = new ArrayList<PersonModel>();
    private Context mContext;
    private RecyclerView recyclerView;
    private PersonAdapter personAdapter;

    public static ListFragment newInstance() {
        // Required empty public constructor
        ListFragment listFragment = new ListFragment();

        return listFragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_list, container, false);

        bus.register(this);

        recyclerView = (RecyclerView) rootView.findViewById(R.id.list_rv);

        //Load and add all data from database to array list
        models = getAll();

        personAdapter = new PersonAdapter(mContext, models);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(mContext);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(personAdapter);
        personAdapter.notifyDataSetChanged();

        return rootView;
    }

    //Load all data from database
    private List<PersonModel> getAll() {
        return new Select()
                .all()
                .from(PersonModel.class)
                .orderBy("NAME ASC")
                .execute();
    }

    //Load the last data added to database
    private List<PersonModel> getLast() {
        return new Select()
                .all()
                .from(PersonModel.class)
                .orderBy("NAME DESC")
                .limit(1)
                .execute();
    }

    //Subscribe to event bus
    //Receive notification/event from MainActivity when added a data to database
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(String STATUS) {
        switch (STATUS) {
            case "NOTIFY":
                //Add last added item to current array list
                models.add(getLast().get(0));

                //refresh recyclerView's adapter
                personAdapter.notifyDataSetChanged();
                break;
            default:
                Log.e(TAG, "Invalid STATUS");
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        this.mContext = context;
    }
}
Jeffy Lee
  • 87
  • 2
  • 9