Android 当执行返回LiveData的数据库操作的线程完成时,如何获得通知?

Android 当执行返回LiveData的数据库操作的线程完成时,如何获得通知?,android,android-room,android-livedata,Android,Android Room,Android Livedata,返回LiveData的数据库操作将在后台线程上自动执行。我需要对返回的LiveData进行一些“后处理”,以便从另一个表中添加信息 但是,执行此处理的代码在实际返回LiveData之前执行得太早 来自执行Dao调用的线程。最终,LiveData包装列表被成功填充,但它的Person对象不包含我打算用以扩充它们的数据(即占有数据) 除非有人能提出更好的总体方法,否则我想做的是确保在从查询线程返回LiveData后调用执行后处理的方法aggregatePersonData 以下精简的代码片段说明了我

返回LiveData的数据库操作将在后台线程上自动执行。我需要对返回的LiveData进行一些“后处理”,以便从另一个表中添加信息

但是,执行此处理的代码在实际返回LiveData之前执行得太早 来自执行Dao调用的线程。最终,LiveData包装列表被成功填充,但它的Person对象不包含我打算用以扩充它们的数据(即占有数据)

除非有人能提出更好的总体方法,否则我想做的是确保在从查询线程返回LiveData后调用执行后处理的方法aggregatePersonData

以下精简的代码片段说明了我的方法

// Person.java
@Entity(tableName = "People")
public class Person
{
    @PrimaryKey(autoGenerate = true)
    private long id;

    // ...

    public long getId()
    {
        return id;
    }

    public void setId(long id)
    {
        this.id = id;
    }

    // ...
}


// from PersonDao.java
@Query("SELECT * FROM People ORDER BY last_name")
LiveData<List<AggregatePerson>> getAllPeople();


// PeoplePossessions is a one-to-many table (i.e., one Person to many Possessions).


// from PersonPossessionDao
@Query("SELECT p.* FROM Possessions p INNER JOIN PeoplePossessions pp ON p.id = pp.possession_id WHERE pp.person_id=:personId")
LiveData<List<Possession>> getPossessionsForPerson(final long personId);


// (not an entity)
// AggregatePerson.java
public class AggregatePerson extends Person
{
    // fields from a join between the People table and (an)other table(s) would go here...

    @Ignore
    private List<String> mPossessions;

    // ...  

    public List<String> getPossessions()
    {
        return mPossessions;
    }

    public void setPossessions(List<String> possessions)
    {
        mPossessions = possessions;
    }
}


// MyRepository.java
public class MyRepository
{
    private PersonDao mPersonDao;
    private PersonPossessionDao mPersonPossessionDao;

    private LiveData<List<AggregatePerson>> mAllPeople;

    public MyRepository(Application application)
    {
        PersonDatabase database = PersonDatabase.getInstance(application);

        // Room automatically executes database operations that return  
        // LiveData objects on a background thread.
        mPersonDao = database.personDao();
        mAllPeople = mPersonDao.getAllPeople();

        mPersonPossessionDao = database.personPossessionDao();
    }

    //...

    public LiveData<List<AggregatePerson>> getAllPeople()
    {
        aggregatePersonData(mAllPeople.getValue());
        return mAllPeople;
    }

    // This method executes too early, before the LiveData<List<AggregatePerson>>
    // has been populated. Thus, the code that adds the possession data is skipped.
    private void aggregatePersonData(List<AggregatePerson> people)
    {
        if (null != people)
        {
            StringBuilder sb = new StringBuilder();
            List<String> items = new ArrayList<>();

            // In this loop, a query is performed for each person.
            for (AggregatePerson person : people)
            {
                long personId = person.getId();
                List<Possession> possessions = mPersonPossessionDao.getPossessionsForPerson(personId);
                if (null != possessions)
                {
                    items.clear();
                    sb.setLength(0);
                    for (int i = 0; i < possessions.size(); i++)
                    {
                        Possession possession = possession.get(i);
                        sb.append(possession.getName());
                        sb.append(": ");
                        sb.append(possession.getValue());
                        sb.append(", ");
                        sb.append(possession.getWeight());
                        items.add(sb.toString());
                    }
                    person.setPossessions(items);
                }

                // more data aggregation for current person would go here...
            }
        }
    }
}
//Person.java
@实体(tableName=“人”)
公共阶层人士
{
@PrimaryKey(自动生成=真)
私人长id;
// ...
公共长getId()
{
返回id;
}
公共无效集合id(长id)
{
this.id=id;
}
// ...
}
//来自PersonDao.java
@查询(“按姓氏从人员订单中选择*)
LiveData getAllPeople();
//PeopleOccessions是一对多表(即,一个人对多个财产)。
//从个人占有到
@查询(“在p.id=pp.Occession\U id,其中pp.person\U id=:personId上从财产p内部连接PeopleOccessions pp中选择p*)
LiveData GetOccessionsForperson(最终长人名);
//(非实体)
//AggregatePerson.java
公共类AggregatePerson扩展Person
{
//来自人员表和其他表之间联接的字段将转到此处。。。
@忽略
私人名单;
// ...  
公共列表
{
归还财产;
}
公共财产(列出财产)
{
财产=财产;
}
}
//MyRepository.java
公共类MyRepository
{
私人私人私人住宅;
私人占有;
个人生活数据;
公共MyRepository(应用程序)
{
PersonDatabase database=PersonDatabase.getInstance(应用程序);
//文件室自动执行返回的数据库操作
//后台线程上的LiveData对象。
mPersonDao=database.personDao();
mAllPeople=mPersonDao.getAllPeople();
mpersonpositiondao=database.personpositiondao();
}
//...
公共LiveData getAllPeople()
{
aggregatePersonData(mallpowers.getValue());
回归民众;
}
//此方法在LiveData之前执行得太早
//已填充。因此,将跳过添加占有数据的代码。
私有void aggregatePersonData(列出人员)
{
如果(空!=人)
{
StringBuilder sb=新的StringBuilder();
列表项=新建ArrayList();
//在这个循环中,为每个人执行一个查询。
for(聚合个人:人)
{
long personId=person.getId();
列表财产=mpersonpositiondao.getpositionsforperson(personId);
如果(空!=财产)
{
items.clear();
sb.设定长度(0);
对于(inti=0;i
因为LiveData的整个要点是让视图观察模型数据的变化,所以我将数据聚合/操作代码从模型层移到了视图层。在那里,我可以在各种查询完成时做出响应,聚合数据,并将其存储在ViewModel中,供UI控制器将来使用。到目前为止,这种方法似乎是有效的。更新:发现毕竟可以使用LiveData在ViewModel层进行观察。每个“源”都可以观察到,因此我现在可以在ViewModel中执行数据聚合,并为UI控制器准备好所有数据。我还使用了CountdownLatch,以便在所有数据聚合完成后,仅在MediatorLiveData上设置值。对于添加到MediatorLiveData的每个源,onChanged()方法中的闩锁计数都会减少。现在,新数据到达时没有UI闪烁,因为所有数据都是在显示之前收集的。