问题
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?
回答1:
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.
回答2:
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.
回答3:
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;
}
}
来源:https://stackoverflow.com/questions/31296754/android-recyclerview-activeandroid