Search code examples
javaandroidrepositoryviewmodelandroid-livedata

How to edit an entry inside View Model / Repository with Live Data


Maybe I'm misunderstanding this all, but how do you edit data using Live Data/View Model/Repository? I see how query all the data, delete an entry, but I want to edit a particular field.

For example, I have 3 things I'm tracking. Date, Time, and Category.I need to be able to change what the category is.

I tried doing something like this in one of my activities:

        budgetViewModel.getAllEntries().observe(this, new Observer<List<BudgetEntry>>() {
            @Override
            public void onChanged(List<BudgetEntry> budgetEntries) {


                Log.i(TAG, "2nd Observer is going off");

                if (manualUpdate == 1) {
                    Log.i(TAG, "MANUAL UPDATE");

                    budgetEntries.get(0).setCategory(updatedCategory);
                    manualUpdate = 0;

                    Log.i(TAG, "Budget Entries: " + budgetEntries.get(0).getCategory());
                }

                else {
                    Log.i(TAG, "No change");
                }


            }
        });
    }

    }

But it doesn't change it permanently. Only for this instance I guess because the Log shows I changed the category, but when I reload the app or check another activity, it still shows the prior data.

I can't find any tutorials on this so any guidance would be most appreciated!

New View Model Changes. I get error cannot create instance of class:

public class BudgetViewModel extends AndroidViewModel {

private BudgetRepository budgetRepository;

//private LiveData<List<BudgetEntry>> allEntries;

LiveData<List<BudgetEntry>> _allEntries = budgetRepository.getAllEntries();
LiveData<List<BudgetEntry>> allEntries = Transformations.map(_allEntries, new Function<List<BudgetEntry>, List<BudgetEntry>>() {
    @Override
    public List<BudgetEntry> apply(List<BudgetEntry> input) {
        return input;
    }
});



public BudgetViewModel(@NonNull Application application) {
    super(application);
    budgetRepository = new BudgetRepository(application);
    //allEntries = budgetRepository.getAllEntries();


}

public void insert (BudgetEntry budgetEntry) {
    budgetRepository.insert(budgetEntry);
}


public void delete (BudgetEntry budgetEntry) {
    budgetRepository.delete(budgetEntry);
}

public void deleteAllEntries () {
    budgetRepository.deleteAllEntries();
}

public LiveData<List<BudgetEntry>> getAllEntries() {
    return _allEntries;
}

public LiveData<Integer> getCount() {
    return budgetRepository.getCount();
}

}

Thanks!


Solution

  • Well I finally figured it out, whoo hoo! I couldn't get the Transformation answer to work so I started researching how to use @Update. I wanted to share in case this help someone in the future, because this one took me weeks. :)

    I was tracking 3 things in my model. Category, Date, Time. My goal was to be able to change ALL category names that matched a particular string to a new string.

    First you need to name your column in your Model:

    @ColumnInfo(name="CATEGORY") private String category;

    Then you need to create a SQL query in your DAO that finds and UPDATES the old category with the new category:

    @Query("UPDATE entry SET CATEGORY = :newcategory WHERE category = :oldcategory")
    void updateColumn(String newcategory, String oldcategory);
    

    This basically says find all categories that match a string, and update them to your new string.

    Now you need to make your methods in your View Model and Repository.

    We will start with the Repository to make an Async Task. First I need to bundle my old category and new category together so I'll make a class in the Repository.

    private static class ParamsSend {
        String newCategory;
        String oldCategory;
    
        ParamsSend(String newCategory, String oldCategory) {
            this.newCategory = newCategory;
            this.oldCategory = oldCategory;
        }
    }
    

    Then I'll create an Async Task passing those parameters.

    private static class UpdateColumnAsyncTask extends AsyncTask<ParamsSend, Void, Void> { private BudgetDao budgetDao;

        private UpdateColumnAsyncTask(BudgetDao budgetDao) {
            this.budgetDao = budgetDao;
        }
    
        @Override
        protected Void doInBackground(ParamsSend... paramsSends) {
            String newCategory = paramsSends[0].newCategory;
            String oldCategory = paramsSends[0].oldCategory;
            budgetDao.updateColumn(newCategory, oldCategory);
            return null;
        }
    }
    

    Then create the method to call the Async Task:

    public void updateColumn(String newCategory, String oldCategory) {
    
        ParamsSend paramsSend  = new ParamsSend(newCategory, oldCategory);
        new UpdateColumnAsyncTask(budgetDao).execute(paramsSend);
    }
    

    Then we will go to the ViewModel and create a method to run the Async Task in the Repoository:

    public void updateColumn(String newCategory, String oldCategory) {
        budgetRepository.updateColumn(newCategory, oldCategory);
    

    Lastly we'll update it in our activity:

             budgetViewModel.updateColumn(updatedCategory, oldCategory);
    

    Good luck all, I hope this helps! :-)