问题
Maybe this is a tiny bit stupid to ask but I am just stuck with this:
I have my Room Database + Entities + Daos.
The entities have a column called "costs" - so basically I wanna sum up all the costs (of course while tracking if there was a new input, so check if the sum has changed - if so, of course change the value/textview) and then simply put the value with .toString() into a TextView.
I already have a RecyclerView+CardView with an Adapter / ViewModel / Repository Class (they put only the Names of the Input into the CardView)
I just don't know where to put the costs stuff - I don't think I need a new ViewModel/Repository but where do I put the sumAllCost() method of my Dao
public class SubRepository {
private SubDAO mSubDao;
private LiveData<List<Sub>> mAllSubs;
SubRepository(Application application){
SubDatabase db = SubDatabase.getInstance(application);
mSubDao = db.getsubDAO();
mAllSubs = mSubDao.getAllSubs();
}
public LiveData<List<Sub>> getAllSubs(){
return mAllSubs;
}
public void insert (Sub sub){
new insertAsyncTask(mSubDao).execute(sub);
}
private static class insertAsyncTask extends AsyncTask<Sub, Void, Void> {
private SubDAO mAsyncTaskDao;
insertAsyncTask (SubDAO dao){
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Sub... params){
mAsyncTaskDao.addSub(params[0]);
return null;
}
}
}
public class SubViewModel extends AndroidViewModel {
private SubRepository mRepository;
private LiveData<List<Sub>> mallSubs;
public SubViewModel (Application application) {
super (application);
mRepository = new SubRepository(application);
mallSubs = mRepository.getAllSubs();
}
public LiveData<List<Sub>> getAllSubs(){
return mallSubs;
}
public void insert (Sub sub){
mRepository.insert(sub);
}}
class HomeSubAdapter extends RecyclerView.Adapter<HomeSubAdapter.ViewHolder> {
List<Sub> subList;
Context context;
private final LayoutInflater mInflater;
public static FragmentManager fragmentManager;
HomeSubAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
//Just wanna show the name so only one tv
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView main_cv_dummy;
public ViewHolder(View itemView) {
super(itemView);
main_cv_dummy = itemView.findViewById(R.id.main_cv_dummy);
}
}
@Override
public HomeSubAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View subview = mInflater.inflate(R.layout.snippet_main_cardview, parent, false);
return new ViewHolder(subview);
}
@Override
public void onBindViewHolder (HomeSubAdapter.ViewHolder holder, final int position) {
if (subList!= null){
final Sub current = subList.get(position);
holder.main_cv_dummy.setText(current.getSubName());
holder.main_cv_dummy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Fragment currentFrag = ShowInfoFragment.newInstance(current);
//fragmentManager.beginTransaction().replace(R.id.compLayout, currentFrag).addToBackStack(null).commit();
Log.d("Clicking: ", current.getSubName() + " was clicked - Listener worked");
}
});
}
else {
holder.main_cv_dummy.setText("Create a new Sub!");
}
}
public void setSubs(List<Sub> subs){
this.subList = subs;
notifyDataSetChanged();
}
@Override
public int getItemCount(){
if(subList!=null){
return subList.size();
} else
{
return 0;
}
}
The Activity with onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Log.d(TAG, "onCreate: starting");
middle_vf = (ViewFlipper)findViewById(R.id.middle_vf);
tv_sum = (TextView) findViewById(R.id.tv_sumCosts);
mSubViewModel = ViewModelProviders.of(this).get(SubViewModel.class);
mSubViewModel.getAllSubs().observe(this, new Observer<List<Sub>>() {
@Override
public void onChanged(@Nullable List<Sub> subs) {
mAdapter.setSubs(subs);
}
});
fragmentManager = getSupportFragmentManager();
//Whenever screen is called - call for recycler view
mRecyclerView = (RecyclerView) findViewById(R.id.main_rv);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//give dummy-subs to Adapter to Recycler
mAdapter = new HomeSubAdapter(this);
mRecyclerView.setAdapter(mAdapter);
setupBottomNavigationView();
setupFAB();
}
I am really not sure about this whole SUM thing
//Get all costs
@Query("SELECT SUM(costs) FROM subscriptions")
void getAllCosts();
//Get all subs
@Query("SELECT * FROM subscriptions")
LiveData<List<Sub>> getAllSubs();
Maybe someone can help - I feel rather stupid right now sorry! I already search several times for a fitting solution but I just cannot find something that helps me (or that I understand)
回答1:
you should provide an alias name to the synthetic column (it might even work without that, but in general, it is easier to access column-names of domain aggregate function results like that):
SELECT SUM(costs) AS value FROM subscriptions
and when a query is expect to return something void
(nothing) cannot be used, that should be the actually returned data-type instead; for monetary values and LiveData
, try LiveData<BigDecimal>
. the documentation also has one relevant example, which might explain it in more detail.
来源:https://stackoverflow.com/questions/54514205/android-room-sum-up-values-and-put-it-in-textview