标签: android-architecture-components

map()和switchMap()方法有什么区别?

LiveData类的这两个方法有什么区别?官方文档和教程对此非常模糊.在map()方法中,第一个参数叫做source,但在switchMap()中它调用了trigger.这背后的理由是什么?

android android-livedata android-architecture-components

42
推荐指数
7
解决办法
9451
查看次数

无法创建ViewModel类的实例

我正在尝试使用Android架构组件编写示例应用程序,但即使在尝试了几天之后我也无法使用它.它给了我以上例外.

生命周期所有者: -

public class MainActivity extends LifecycleActivity {

    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.tv_user);
        PostViewModel viewModel = ViewModelProviders.of(this).get(PostViewModel.class);
        viewModel.loadPosts();
        viewModel.getPost().observe(this, new Observer<Post>() {
            @Override
            public void onChanged(@Nullable Post post) {
                if(post != null) {
                    textView.setText(post.toString());
                }
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型: -

public class PostViewModel extends ViewModel {
    private MediatorLiveData<Post> post;
    private PostRepository postRepo;

    PostViewModel() {
        post = new MediatorLiveData<>();
        postRepo = new PostRepository();
    }

    public LiveData<Post> loadPosts() {
        post.addSource(postRepo.getPost(),
                post -> this.post.setValue(post)
        ); …
Run Code Online (Sandbox Code Playgroud)

android mvvm android-architecture-components

41
推荐指数
14
解决办法
3万
查看次数

为什么要为新连接的观察者触发两次LiveData观察者

我的理解LiveData是,它将触发观察者对当前状态变化的数据,而不是一系列历史状态变化的数据.

目前,我有一个MainFragment执行Room写操作的程序,用于将非删除数据更改为已删除的数据.

我也是另一个TrashFragment观察到破坏数据的人.

请考虑以下情形.

  1. 目前有0个已删除的数据.
  2. MainFragment是当前活动的片段.TrashFragment尚未创建.
  3. MainFragment添加了1个已删除的数据.
  4. 现在,有1个已删除的数据
  5. 我们采用抽屉式导航来代替MainFragmentTrashFragment.
  6. TrashFragment的观察者将首先收到onChanged0个已删除的数据
  7. 再次,TrashFragment观察者将接下来接收onChanged1个已删除的数据

我的期望是,第(6)项不应该发生.TrashFragment应该只接收最新的已删除数据,即1.

这是我的代码


TrashFragment.java

public class TrashFragment extends Fragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        noteViewModel = ViewModelProviders.of(getActivity()).get(NoteViewModel.class);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { …
Run Code Online (Sandbox Code Playgroud)

android android-livedata android-architecture-components

41
推荐指数
9
解决办法
3万
查看次数

MVVM模式和startActivity

我最近决定仔细研究一下Google发布的新Android架构组件,特别是将他们的ViewModel生命周期感知类用于MVVM架构和LiveData.

只要我处理单个活动或单个碎片,一切都很好.

但是,我找不到一个很好的解决方案来处理Activity切换.比如说,为了一个简短的例子,活动A有一个按钮来启动活动B.

startActivity()在哪里处理?

遵循MVVM模式,clickListener的逻辑应该在ViewModel中.但是,我们希望避免在那里引用Activity.因此,将上下文传递给ViewModel不是一种选择.

我缩小了几个似乎"没问题"的选项,但却找不到任何正确的答案"这里是怎么做的".

选项1:在ViewModel中有一个枚举,其值映射到可能的路由(ACTIVITY_B,ACTIVITY_C).将此与LiveData结合使用.活动将观察此LiveData,并且当ViewModel决定应该启动ACTIVITY_C时,它只是postValue(ACTIVITY_C).然后,Activity可以正常调用startActivity().

选项2:常规接口模式.与选项1的原理相同,但Activity将实现接口.虽然我觉得与此有点联系.

选项3:消息选项,例如Otto或类似的.ViewModel发送一个Broadcast,Activity选择它并启动它所拥有的内容.此解决方案的唯一问题是,默认情况下,您应该将该广播的注册/取消注册放在ViewModel中.所以没有帮助.

选项4:拥有一个大的路由类,在某个地方,作为单例或类似的,可以被调用以将相关路由分派给任何活动.最终通过界面?所以每个活动(或BaseActivity)都会实现

IRouting { void requestLaunchActivity(ACTIVITY_B); }
Run Code Online (Sandbox Code Playgroud)

当你的应用程序开始有很多片段/活动时,这个方法让我有点担心(因为路由类会变得很大)

就是这样了.那是我的问题.你们是怎么处理这个的?你选择了我没想过的选择吗?您认为最相关的选项是什么?为什么?推荐的Google方法是什么?

PS:没有把我带到任何地方的链接1 - Android ViewModel调用Activity方法 2 - 如何从普通的非活动java类启动活动?

android mvvm android-architecture-components

40
推荐指数
1
解决办法
8839
查看次数

导航架构组件 - 对话框片段

是否可以使用带有DialogFragment的新导航架构组件?我是否必须创建自定义导航器?

我很乐意将它们与导航图中的新功能结合使用.

android android-architecture-components android-jetpack android-architecture-navigation

39
推荐指数
4
解决办法
1万
查看次数

如何清除LiveData存储值?

根据LiveData文档:

LiveData类具有以下优点:

...

始终是最新数据:如果生命周期再次启动(如从后端堆栈返回到启动状态的活动),它将收到最新的位置数据(如果尚未生成).

但有时候我不需要这个功能.

例如,我在ViewModel中跟随LiveData,在Activity中跟踪Observer:

//LiveData
val showDialogLiveData = MutableLiveData<String>()

//Activity
viewModel.showMessageLiveData.observe(this, android.arch.lifecycle.Observer { message ->
        AlertDialog.Builder(this)
                .setMessage(message)
                .setPositiveButton("OK") { _, _ -> }
                .show()
    })
Run Code Online (Sandbox Code Playgroud)

现在每次旋转后都会出现旧的对话框.

有没有办法在处理后清除存储的值或者根本没有使用LiveData?

android android-livedata android-architecture-components

36
推荐指数
4
解决办法
2万
查看次数

警告:警告:注释处理器'android.arch.lifecycle.LifecycleProcessor'支持的源版本'RELEASE_7'小于-source'1.8'

尝试使用Android Studio 3 Canary 5与Architecture Components和Kotlin构建示例时会发出此警告.

谁能告诉我原因?

谢谢,Ove

编辑#1:这是Dan Lew不久前制作的一个样本

https://github.com/dlew/android-architecture-counter-sample

的build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 25
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        applicationId "net.danlew.counter"
        minSdkVersion 23
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    compile "com.android.support:recyclerview-v7:${rootProject.ext.supportLibVersion}"
    compile "com.android.support:design:${rootProject.ext.supportLibVersion}"
    compile "com.android.support:cardview-v7:${rootProject.ext.supportLibVersion}"
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-studio android-architecture-components

36
推荐指数
2
解决办法
1万
查看次数

如何以及在何处使用Transformations.switchMap?

在Google最近发布的Android Architecture Components库中,我们在Transformations类中有两个静态函数.虽然map功能很直接且易于理解,但我发现很难正确理解该switchMap功能.

可以在此处找到switchMap的官方文档.

有人可以用一个实际的例子解释如何以及在哪里使用switchMap功能?

android android-livedata android-architecture-components

36
推荐指数
4
解决办法
2万
查看次数

手动清除Android ViewModel?

参考android.arch.lifecycle.ViewModel课程.

ViewModel限定在与其相关的UI组件的生命周期中,因此在Fragment基于应用程序的应用程序中,这将是片段生命周期.这是一件好事.


在某些情况下,人们想要ViewModel在多个片段之间共享实例.具体而言,我对许多屏幕与相同基础数据相关的情况感兴趣.

(当多个相关片段显示在同一个屏幕上时,文档提出了相似的方法,但这可以通过使用单个宿主片段来解决,如下面的答案所示.)

这在官方ViewModel文档中讨论:

ViewModels还可以用作活动的不同片段之间的通信层.每个Fragment都可以通过其Activity使用相同的密钥获取ViewModel.这允许以解耦方式在片段之间进行通信,使得它们永远不需要直接与其他片段对话.

换句话说,要在表示不同屏幕的片段之间共享信息,ViewModel应将其范围限定为Activity生命周期(并且根据Android文档,这也可以在其他共享实例中使用).


现在,在新的Jetpack导航模式中,建议使用"One Activity/Many Fragments"架构.这意味着活动在应用程序使用的整个过程中都存在.

即任何ViewModel作用于Activity生命周期的共享实例永远不会被清除 - 内存仍然在不断使用.

为了保留内存并在任何时间点使用尽可能少的内容,能够ViewModel在不再需要时清除共享实例会很好.


如何ViewModel从它ViewModelStore或持有者片段手动清除?

android android-viewmodel android-architecture-components android-jetpack

36
推荐指数
5
解决办法
7780
查看次数

Android会议室:订单不工作

我正在使用新的Android ORM Room.我遇到了以下问题,使用带参数的ORDER BY的查询不起作用.

如果我想使用从ORDER BY的参数填充的字段,它不起作用.它只是没有任何排序.

@Query("SELECT * FROM User ORDER BY :orderBY ASC")
List<User> sortedFind(String orderBY);
Run Code Online (Sandbox Code Playgroud)

但是,当我将ORDER BY列直接放在查询中以对结果进行排序时,它会按预期工作.

@Query("SELECT * FROM User ORDER BY name ASC")
List<User> sortedFind();
Run Code Online (Sandbox Code Playgroud)

这是Android Room上的错误,还是我做错了什么?

android android-room android-architecture-components

34
推荐指数
3
解决办法
2万
查看次数