Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android:MVVM模式下屏幕旋转时UI和数据不存在_Java_Android_Mvvm_Data Binding_Android Databinding - Fatal编程技术网

Java Android:MVVM模式下屏幕旋转时UI和数据不存在

Java Android:MVVM模式下屏幕旋转时UI和数据不存在,java,android,mvvm,data-binding,android-databinding,Java,Android,Mvvm,Data Binding,Android Databinding,我尝试在我的活动中实现从这里显示数据:()。我尝试使用数据绑定更新UI,一切都很顺利,直到我尝试旋转屏幕,我从logcat中看到数据总是重新加载,我的ImageView总是刷新,这是我的活动: public class DetailActivity extends BaseActivity<ActivityDetailBinding, DetailViewModel> implements DetailNavigator { @Inject ViewMode

我尝试在我的
活动中实现从这里显示数据:()。我尝试使用数据绑定更新UI,一切都很顺利,直到我尝试旋转屏幕,我从
logcat
中看到数据总是重新加载,我的
ImageView
总是刷新,这是我的活动:

     public class DetailActivity extends BaseActivity<ActivityDetailBinding, DetailViewModel> implements DetailNavigator {
    @Inject
    ViewModelProviderFactory factory;

    private DetailViewModel detailViewModel;

    public static final String INTENT_ID = "id_intent";

    public static final String INTENT_FLAG = "id_flag";

    private ActivityDetailBinding mActivityDetailBinding;

    public static Intent newIntent(Context context) {
        return new Intent(context, DetailActivity.class);
    }

    @Override
    public int getBindingVariable() {
        return BR.viewModel;
    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_detail;
    }

    @Override
    public DetailViewModel getViewModel() { 
detailViewModel = ViewModelProviders.of(this, factory).get(DetailViewModel.class);
        return detailViewModel;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        detailViewModel.setNavigator(this);
        mActivityDetailBinding = getViewDataBinding();
        initView();
        initData(savedInstanceState);

    }


    private void initData(Bundle savedInstanceState) {
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            int id = extras.getInt(INTENT_ID, 0);
            int flag = extras.getInt(INTENT_FLAG, 0);
            detailViewModel.fetchDetail(id, flag);
        }
    }

    private void initView() {
        if (getSupportActionBar() != null) {
            getSupportActionBar().hide();
        }
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }


    @Override
    public void ShowProgressDialog(Boolean loading) {
        if (loading) {
            showLoading();
        } else {
            hideLoading();
        }
    }
    }
这是我的
ViewModelFactory
类:

@Singleton
public class ViewModelProviderFactory extends ViewModelProvider.NewInstanceFactory {

    private final DataManager dataManager;
    private final SchedulerProvider schedulerProvider;

    @Inject
    public ViewModelProviderFactory(DataManager dataManager,
                                    SchedulerProvider schedulerProvider) {
        this.dataManager = dataManager;
        this.schedulerProvider = schedulerProvider;
    }

    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        if (modelClass.isAssignableFrom(DetailViewModel.class)) {
            return (T) new DetailViewModel(dataManager,schedulerProvider);
        }
        throw new IllegalArgumentException("Unknown class name");
    }
}
    public class DetailViewModel extends BaseViewModel<DetailNavigator> {

    private final ObservableField<String> originalName = new ObservableField<>();
    private final ObservableField<String> releaseDate = new ObservableField<>();
    private final ObservableField<String> overview = new ObservableField<>();
    private final ObservableField<String> genreMovie = new ObservableField<>();
    private final ObservableField<String> posterPath = new ObservableField<>();
    private final ObservableField<String> voteAverage = new ObservableField<>();

    public DetailViewModel(DataManager dataManager, SchedulerProvider schedulerProvider) {
        super(dataManager, schedulerProvider);
    }

    public void fetchDetail(int id, int flag) {
        if (flag == 1) {
            getNavigator().ShowProgressDialog(true);
            getCompositeDisposable().add(getDataManager()
                    .getApiHelper().doDetailMovie(id, URLConfig.API_KEY, getDataManager().getLanguage())
                    .subscribeOn(getSchedulerProvider().io())
                    .observeOn(getSchedulerProvider().ui())
                    .subscribe(detailResponse -> {
                        setUpData(detailResponse);
                        getNavigator().ShowProgressDialog(false);
//                        getNavigator().updateView();
                    }, throwable -> {
                        getNavigator().ShowProgressDialog(false);
                    }));
        } else if (flag == 2) {
            getNavigator().ShowProgressDialog(true);
            getCompositeDisposable().add(getDataManager()
                    .getApiHelper().doDetailTV(id, URLConfig.API_KEY, getDataManager().getLanguage())
                    .subscribeOn(getSchedulerProvider().io())
                    .observeOn(getSchedulerProvider().ui())
                    .subscribe(detailResponse -> {
                        setUpData(detailResponse);
                        getNavigator().ShowProgressDialog(false);
                    }, throwable -> {
                        getNavigator().ShowProgressDialog(false);
                    }));
        }
    }

    private void setUpData(DetailResponse detailResponse) {
        if (detailResponse.getOriginal_name() != null) {
            originalName.set(detailResponse.getOriginal_name());
        } else if (detailResponse.getOriginal_title() != null) {
            originalName.set(detailResponse.getOriginal_title());
        } else {

        }

        if (detailResponse.getFirst_air_date() != null) {
            releaseDate.set(detailResponse.getFirst_air_date());
        } else {
            releaseDate.set(detailResponse.getRelease_date());
        }

        if (!detailResponse.getOverview().equals("")) {
            overview.set(detailResponse.getOverview());
        } else {
            overview.set(getNavigator().noDesc());
        }

        posterPath.set(String.valueOf(detailResponse.getPoster_path()));

        voteAverage.set(String.valueOf(detailResponse.getVote_average()));

        String genres = "";

        for (int i = 0; i < detailResponse.getGenreList().size(); i++) {
            genres = genres + detailResponse.getGenreList().get(i).getName();
            if (i != detailResponse.getGenreList().size() - 1) {
                genres = genres + ", ";
            }
        }

        genreMovie.set(genres);

    }

    public ObservableField<String> getOriginalName() {
        return originalName;
    }

    public ObservableField<String> getReleaseDate() {
        return releaseDate;
    }

    public ObservableField<String> getOverview() {
        return overview;
    }

    public ObservableField<String> getGenreMovie() {
        return genreMovie;
    }

    public ObservableField<String> getPosterPath() {
        return posterPath;
    }

    public ObservableField<String> getVoteAverage() {
        return voteAverage;
    }
}
这是我的
DetailResponse
课程:

public class DetailResponse {
    @SerializedName("original_name")
    private String original_name ;
    @SerializedName("original_title")
    private String original_title ;
    @SerializedName("release_date")
    private String release_date ;
    @SerializedName("first_air_date")
    private String first_air_date ;
    @SerializedName("vote_average")
    private Double vote_average ;
    @SerializedName("overview")
    private String overview ;
    @SerializedName("poster_path")
    private String poster_path;
    @SerializedName("genres")
    private List<Genre> genreList;

    public String getOriginal_name() {
        return original_name;
    }

    public String getOriginal_title() {
        return original_title;
    }

    public String getRelease_date() {
        return release_date;
    }

    public String getFirst_air_date() {
        return first_air_date;
    }

    public Double getVote_average() {
        return vote_average;
    }

    public String getOverview() {
        return overview;
    }

    public String getPoster_path() {
        return poster_path;
    }

    public List<Genre> getGenreList() {
        return genreList;
    }

    public static class Genre{
        @SerializedName("name")
        private String name ;

        public String getName() {
            return name;
        }
    }
}
公共类详细信息响应{
@SerializedName(“原始名称”)
私有字符串原始名称;
@序列化名称(“原始标题”)
私有字符串原始标题;
@序列化名称(“发布日期”)
私有字符串发布日期;
@序列化名称(“首次发布日期”)
私有字符串首个\u air\u日期;
@序列化名称(“投票平均值”)
私人双票平均;
@序列化名称(“概述”)
私有字符串概述;
@序列化名称(“海报路径”)
私家车路线;;
@序列化名称(“流派”)
私有列表genreList;
公共字符串getOriginal_name(){
返回原始名称;
}
公共字符串getOriginal_title(){
返回原始标题;
}
公共字符串getRelease_date(){
返回发布日期;
}
公共字符串getFirst\u air\u date(){
返回第一个空气日期;
}
公众双倍投票(平均值){
返回平均值;
}
公共字符串getOverview(){
退货概述;
}
公共字符串getPoster_path(){
回程;;
}
公共列表getGenreList(){
返回genreList;
}
公共静态类体裁{
@序列化名称(“名称”)
私有字符串名称;
公共字符串getName(){
返回名称;
}
}
}
最后一个,我是如何尝试使用数据绑定在UI中获取数据的,这是我的布局:

  <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.detail.DetailActivity">

    <data>

        <import type="android.view.View" />
        <variable
            name="viewModel"
            type="id.dicoding.eriza.moviecatalogue.ui.detail.DetailViewModel" />
    </data>
<androidx.core.widget.NestedScrollView
    android:id="@+id/nestedScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:animateLayoutChanges="true">

        <com.github.florent37.shapeofview.shapes.ArcView
            android:id="@+id/shape_header"
            android:layout_width="match_parent"
            android:layout_height="@dimen/size300dp"
            android:alpha="0.7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:shape_arc_cropDirection="outside"
            app:shape_arc_height="@dimen/size30dp"
            app:shape_arc_position="bottom">

            <com.flaviofaria.kenburnsview.KenBurnsView
                android:id="@+id/image_header"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:src="@drawable/poster_avengerinfinity"
                app:imageDetailUrl="@{viewModel.posterPath}"
                android:tint="#6F000000" />

        </com.github.florent37.shapeofview.shapes.ArcView>

        <com.github.florent37.shapeofview.shapes.RoundRectView
            android:id="@+id/shape_poster"
            android:layout_width="@dimen/size150dp"
            android:layout_height="@dimen/size200dp"
            android:layout_marginTop="@dimen/margin250dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/shape_header"
            app:shape_roundRect_bottomLeftRadius="@dimen/corner10dp"
            app:shape_roundRect_bottomRightRadius="@dimen/corner10dp"
            app:shape_roundRect_topLeftRadius="@dimen/corner10dp"
            app:shape_roundRect_topRightRadius="@dimen/corner10dp">

            <ImageView
                android:id="@+id/image_poster"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:contentDescription="@string/hint_poster"
                android:scaleType="fitXY"
                app:imageDetailUrl="@{viewModel.posterPath}"
                android:src="@drawable/poster_avengerinfinity" />

        </com.github.florent37.shapeofview.shapes.RoundRectView>

        <TextView
            android:id="@+id/text_title"
            style="@style/FontText.Title.Detail"
            android:layout_marginTop="@dimen/margin15dp"
            android:textSize="@dimen/font_large_size"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/shape_poster"
            android:text="@{viewModel.originalName}"
            tools:text="@string/hint_title" />

        <TextView
            android:id="@+id/text_title_release"
            style="@style/FontText"
            android:layout_marginTop="@dimen/margin10dp"
            android:text="@string/text_release"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintTop_toBottomOf="@+id/text_title" />

        <TextView
            android:id="@+id/text_release"
            style="@style/FontText"
            android:layout_marginStart="@dimen/margin2dp"
            android:layout_marginTop="@dimen/margin10dp"
            android:text="@{viewModel.releaseDate}"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintStart_toEndOf="@+id/text_title_release"
            app:layout_constraintTop_toBottomOf="@+id/text_title"
            tools:text="@string/hint_release" />

        <TextView
            android:id="@+id/text_genres"
            style="@style/FontText.Normal"
            android:layout_marginStart="@dimen/margin15dp"
            android:layout_marginTop="@dimen/margin10dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text_release"
            android:text="@{viewModel.genreMovie}"
            tools:text="@string/hint_genres" />
        <RatingBar
            android:id="@+id/rating_bar"
            android:layout_width="wrap_content"
            android:layout_height="45dp"
            android:layout_marginStart="@dimen/margin15dp"
            android:layout_marginTop="@dimen/margin5dp"
            android:isIndicator="true"
            android:numStars="5"
            android:rating="3.8"
            android:stepSize="0.1"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintStart_toStartOf="parent"
            app:ratingBar="@{viewModel.voteAverage}"
            app:layout_constraintTop_toBottomOf="@+id/text_genres" />

        <TextView
            android:id="@+id/text_rating"
            style="@style/FontText.Rating.Orange"
            android:layout_marginStart="@dimen/margin5dp"
            app:layout_constraintRight_toLeftOf="parent"
            app:layout_constraintStart_toEndOf="@+id/rating_bar"
            app:layout_constraintTop_toBottomOf="@+id/text_genres"
            android:text="@{viewModel.voteAverage}"
            tools:text="@string/hit_rating" />

        <TextView
            android:id="@+id/text_default_rating"
            style="@style/FontText.Rating"
            android:textStyle="normal"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintRight_toLeftOf="parent"
            app:layout_constraintStart_toEndOf="@+id/text_rating"
            app:layout_constraintTop_toBottomOf="@+id/text_genres"
            android:text="@string/hint_default_rating" />

        <TextView
            android:id="@+id/text_desc"
            style="@style/FontText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/margin15dp"
            android:layout_marginTop="@dimen/margin25dp"
            android:layout_marginEnd="@dimen/margin15dp"
            android:paddingBottom="@dimen/padding100dp"
            app:layout_constraintTop_toBottomOf="@+id/rating_bar"
            android:text="@{viewModel.overview}"
            tools:text="@string/hint_desc" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.5" />

    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.core.widget.NestedScrollView>
</layout>

我认为
ViewModel
应该管理活动生命周期中相关数据的UI,tt允许在应用程序中保留配置更改,但在我的情况下,
data
是保留的,但是当我检查
logcat
时,
fetchDetail()
DetailViewModel
类中的
在屏幕旋转时总是被调用,而我的
ImageView
在我旋转屏幕时也会刷新,所以我认为
viewModel
在屏幕旋转时不会管理我的UI。我的代码有问题吗


希望任何人都能帮助我,告诉我哪里是我的错,我必须做什么。非常感谢。

打开应用程序。之后进入飞行模式。然后旋转屏幕。检查viewmodel是否在配置更改后仍然有效。
viewmodel
在飞机模式下的配置更改时仍然有效,并且
ImageView
是alos survive,但是我在没有连接时设置的
视图
的一些可见性:消失了,并且只有当
活动
第一次创建说
没有连接
时才会显示一条错误消息。我不明白的是为什么方法
FetchDetail()
当我旋转屏幕时,是否总是调用?这使得我的
ViewModel
无法保存已经存在的UIcreated@user1506104因此
ViewModel
无法避免调用
onCreate()
Activity
  <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.detail.DetailActivity">

    <data>

        <import type="android.view.View" />
        <variable
            name="viewModel"
            type="id.dicoding.eriza.moviecatalogue.ui.detail.DetailViewModel" />
    </data>
<androidx.core.widget.NestedScrollView
    android:id="@+id/nestedScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:animateLayoutChanges="true">

        <com.github.florent37.shapeofview.shapes.ArcView
            android:id="@+id/shape_header"
            android:layout_width="match_parent"
            android:layout_height="@dimen/size300dp"
            android:alpha="0.7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:shape_arc_cropDirection="outside"
            app:shape_arc_height="@dimen/size30dp"
            app:shape_arc_position="bottom">

            <com.flaviofaria.kenburnsview.KenBurnsView
                android:id="@+id/image_header"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:src="@drawable/poster_avengerinfinity"
                app:imageDetailUrl="@{viewModel.posterPath}"
                android:tint="#6F000000" />

        </com.github.florent37.shapeofview.shapes.ArcView>

        <com.github.florent37.shapeofview.shapes.RoundRectView
            android:id="@+id/shape_poster"
            android:layout_width="@dimen/size150dp"
            android:layout_height="@dimen/size200dp"
            android:layout_marginTop="@dimen/margin250dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/shape_header"
            app:shape_roundRect_bottomLeftRadius="@dimen/corner10dp"
            app:shape_roundRect_bottomRightRadius="@dimen/corner10dp"
            app:shape_roundRect_topLeftRadius="@dimen/corner10dp"
            app:shape_roundRect_topRightRadius="@dimen/corner10dp">

            <ImageView
                android:id="@+id/image_poster"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:contentDescription="@string/hint_poster"
                android:scaleType="fitXY"
                app:imageDetailUrl="@{viewModel.posterPath}"
                android:src="@drawable/poster_avengerinfinity" />

        </com.github.florent37.shapeofview.shapes.RoundRectView>

        <TextView
            android:id="@+id/text_title"
            style="@style/FontText.Title.Detail"
            android:layout_marginTop="@dimen/margin15dp"
            android:textSize="@dimen/font_large_size"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/shape_poster"
            android:text="@{viewModel.originalName}"
            tools:text="@string/hint_title" />

        <TextView
            android:id="@+id/text_title_release"
            style="@style/FontText"
            android:layout_marginTop="@dimen/margin10dp"
            android:text="@string/text_release"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintTop_toBottomOf="@+id/text_title" />

        <TextView
            android:id="@+id/text_release"
            style="@style/FontText"
            android:layout_marginStart="@dimen/margin2dp"
            android:layout_marginTop="@dimen/margin10dp"
            android:text="@{viewModel.releaseDate}"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintStart_toEndOf="@+id/text_title_release"
            app:layout_constraintTop_toBottomOf="@+id/text_title"
            tools:text="@string/hint_release" />

        <TextView
            android:id="@+id/text_genres"
            style="@style/FontText.Normal"
            android:layout_marginStart="@dimen/margin15dp"
            android:layout_marginTop="@dimen/margin10dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text_release"
            android:text="@{viewModel.genreMovie}"
            tools:text="@string/hint_genres" />
        <RatingBar
            android:id="@+id/rating_bar"
            android:layout_width="wrap_content"
            android:layout_height="45dp"
            android:layout_marginStart="@dimen/margin15dp"
            android:layout_marginTop="@dimen/margin5dp"
            android:isIndicator="true"
            android:numStars="5"
            android:rating="3.8"
            android:stepSize="0.1"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintStart_toStartOf="parent"
            app:ratingBar="@{viewModel.voteAverage}"
            app:layout_constraintTop_toBottomOf="@+id/text_genres" />

        <TextView
            android:id="@+id/text_rating"
            style="@style/FontText.Rating.Orange"
            android:layout_marginStart="@dimen/margin5dp"
            app:layout_constraintRight_toLeftOf="parent"
            app:layout_constraintStart_toEndOf="@+id/rating_bar"
            app:layout_constraintTop_toBottomOf="@+id/text_genres"
            android:text="@{viewModel.voteAverage}"
            tools:text="@string/hit_rating" />

        <TextView
            android:id="@+id/text_default_rating"
            style="@style/FontText.Rating"
            android:textStyle="normal"
            android:visibility="@{viewModel.isConnected ? View.VISIBLE : View.GONE}"
            app:layout_constraintRight_toLeftOf="parent"
            app:layout_constraintStart_toEndOf="@+id/text_rating"
            app:layout_constraintTop_toBottomOf="@+id/text_genres"
            android:text="@string/hint_default_rating" />

        <TextView
            android:id="@+id/text_desc"
            style="@style/FontText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/margin15dp"
            android:layout_marginTop="@dimen/margin25dp"
            android:layout_marginEnd="@dimen/margin15dp"
            android:paddingBottom="@dimen/padding100dp"
            app:layout_constraintTop_toBottomOf="@+id/rating_bar"
            android:text="@{viewModel.overview}"
            tools:text="@string/hint_desc" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.5" />

    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.core.widget.NestedScrollView>
</layout>