【问题标题】:How to edit an entry inside View Model / Repository with Live Data如何使用实时数据编辑视图模型/存储库中的条目
【发布时间】:2021-01-05 17:23:32
【问题描述】:

也许我误解了这一切,但是您如何使用 Live Data/View Model/Repository 编辑数据?我知道如何查询所有数据,删除一个条目,但我想编辑一个特定字段。

例如,我正在跟踪 3 件事。日期、时间和类别。我需要能够更改类别。

我尝试在我的一项活动中做这样的事情:

        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");
                }


            }
        });
    }

    }

但它不会永久改变它。仅对于这种情况,我猜是因为日志显示我更改了类别,但是当我重新加载应用程序或检查其他活动时,它仍然显示之前的数据。

我找不到这方面的任何教程,因此非常感谢任何指导!

新视图模型更改。我得到错误无法创建类的实例:

公共类 BudgetViewModel 扩展 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();
}

}

谢谢!

【问题讨论】:

    标签: java android repository viewmodel android-livedata


    【解决方案1】:

    您可以为此在 ViewModel 中使用 Transformations.map 函数。

    将主线程上的给定函数应用于源 LiveData 发出的每个值并返回 LiveData,后者发出结果值。

    给定的函数 func 将在主线程上执行。

    科特林

    import androidx.lifecycle.*
    
    class YourViewModel : ViewModel() {
      private val _allEntries: LiveData<List<BudgetEntry>> = budgetRepository.getAllEntries()
      val allEntries: LiveData<List<BudgetEntry>> = Transformations.map(_allEntries) { list: List<BudgetEntry> ->
        list.map { budgetEntry ->
           budgetEntry.setCategory(updatedCategorya)
        }
      }
    }
    

    Java

    import androidx.lifecycle.*;
    
    class YourViewModel extends ViewModel {
      private final LiveData<List<BudgetEntry>> _allEntries = budgetRepository.getAllEntries();
      final LiveData<List<BudgetEntry>> allEntries = Transformations.map(_allEntries, new Function<List<BudgetEntry>, List<BudgetEntry>>() {
            @Override
            public List<BudgetEntry> apply(List<BudgetEntry> input) {
                // do the mapping for each budgetEntry
                return // mapped list
            }
        });
    }
    

    现在您可以像往常一样观察allEntriesmap 函数负责更新 LiveData。

    【讨论】:

    • 感谢您的信息!我尝试实现您提到的内容,但得到“无法创建类的实例”。我更新了我的问题以显示我的视图模型现在的样子。你对此有什么建议吗?谢谢!
    • 哪个实例,哪个类不能创建?究竟在哪里?否则我只能猜测。
    • 无法创建类 android.example.com.budgetkeeper.Models.BudgetViewModel 的实例,然后它说:Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.lifecycle.空对象引用上的 LiveData android.example.com.budgetkeeper.Database.BudgetRepository.getAllEntries()'。我认为这与不在构造函数中调用 allEntries 有关。如果有帮助,我的视图模型在上面的主要问题中。再次感谢!
    • 您的BudgetRepository 为空,因为您正在访问存储库(在构造函数上方)budgetRepository.getAllEntries();,然后在下面的构造函数中创建它。创建存储库后,您也可以在构造函数中为 LiveData 进行分配。
    【解决方案2】:

    好吧,我终于想通了,哇哦!我无法让转换答案起作用,所以我开始研究如何使用@Update。我想分享一下,以防将来对某人有所帮助,因为这花了我数周时间。 :)

    我在我的模型中跟踪 3 件事。类别、日期、时间。我的目标是能够将与特定字符串匹配的所有类别名称更改为新字符串。

    首先你需要在你的模型中命名你的列:

    @ColumnInfo(name="CATEGORY") 私有字符串类别;

    然后您需要在您的 DAO 中创建一个 SQL 查询,以查找并使用新类别更新旧类别:

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

    这基本上是说找到与字符串匹配的所有类别,并将它们更新为您的新字符串。

    现在您需要在视图模型和存储库中创建方法。

    我们将从存储库开始创建一个异步任务。首先,我需要将旧类别和新类别捆绑在一起,以便在存储库中创建一个类。

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

    然后我将创建一个传递这些参数的异步任务。

    私有静态类 UpdateColumnAsyncTask 扩展 AsyncTask { 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;
        }
    }
    

    然后创建调用异步任务的方法:

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

    然后我们将进入 ViewModel 并创建一个方法来运行 Repoository 中的 Async Task:

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

    最后我们将在我们的活动中更新它:

             budgetViewModel.updateColumn(updatedCategory, oldCategory);
    

    祝大家好运,我希望这会有所帮助! :-)

    【讨论】:

      猜你喜欢
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      相关资源
      最近更新 更多