如何使用数据绑定显示一个继承自BaseActivity的childActivity?

5
我正在使用一个基础活动作为另一个活动“RecicpeActivity”的父活动,因为我已经覆盖了基础活动中的setContentView方法,以便子活动可以使用它并将其布局传递给要填充在框架布局中的页面。 子活动“RecicpeActivity”使用DataBinding设置其视图。 我所做的是将子活动的布局尝试填充到基础活动中的一个框架布局“container”中,但是数据绑定根本没有被考虑,因为在调试过程中显示出现空白屏幕,即使我已经看到子活动的布局作为框架布局的子级。
我尝试了两种方式: 1- 第一种方式是通过调用setContentView来传递子活动的布局,然后将传递的布局填充到基础活动的框架布局中。 2- 第二种方式是在基础活动中使用数据绑定,但我认为这无关紧要。
_ChildActivity
public class RecipeActivity extends BaseActivity {
private ActivityRecipeBinding mBinding;
private static final String RECIPE_INTENT_KEY = "recipe key";
private ScrollView mScrollView;
private RecipeViewModel recipeViewModel;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    recipeViewModel = 
          ViewModelProviders.of(this).get(RecipeViewModel.class);
    mBinding = DataBindingUtil.inflate(
                getLayoutInflater(), 
                R.layout.activity_recipe, null, false);
    setContentView(R.layout.activity_recipe);

    // This method is implemented in the BaseActivity.
    showProgressBar(true);
    recipeViewModel.getRecipe().observe(this, new Observer<Recipe>() {
        @Override
        public void onChanged(Recipe recipe) {
            if (recipe != null){
                if (recipe.getRecipe_id().equals(
                    recipeViewModel.getRecipeId())){
                    mBinding.setRecipe(recipe);
                    mScrollView.setVisibility(View.VISIBLE);
                    showProgressBar(false);

                }
            }
        }
    });
    recipeViewModel.getRecipeById(getIncomingIntentRecipeId());
}

private String getIncomingIntentRecipeId(){
    if (getIntent().hasExtra(RECIPE_INTENT_KEY)){
        String recipe_id = getIntent().getStringExtra(RECIPE_INTENT_KEY);
        return recipe_id;
    }
    return null;
}

_BaseActivity

 public abstract class BaseActivity extends AppCompatActivity {
    public ProgressBar mProgressBar;

    @Override
    public void setContentView(int layoutResID) {

        RelativeLayout mRelativeLayout  = 
       (RelativeLayout) getLayoutInflater().inflate(
          R.layout.activity_base, null);
        FrameLayout frameLayout = mRelativeLayout.findViewById(
          R.id.activity_content);
        mProgressBar = mRelativeLayout.findViewById(R.id.progress_bar)

        /**
         * True means layoutResID should be inflated and made a part of
            parent frameLayout
         */
        getLayoutInflater().inflate(layoutResID, frameLayout, true);
        super.setContentView(mRelativeLayout);
    }

    public void showProgressBar(boolean visibility){
        mProgressBar.setVisibility(visibility ?
                  View.VISIBLE : View.INVISIBLE);
    }

_ChildActivity Layout "activity_recipe"

   <?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">

        <data>
            <variable
                name="recipe"
                type="com.mustafa.foodapp.models.Recipe" />

            <import type="com.mustafa.foodapp.util.StringUtils" />
        </data>

        <ScrollView
            android:id="@+id/parent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="visible">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <ImageView
                    android:id="@+id/recipe_image"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/recipe_image_height"
                    android:scaleType="center"
                    app:imageUrl="@{recipe.image_url}" />

                <TextView
                    android:id="@+id/recipe_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/recipe_image"
                    android:padding="7dp"
                    android:text="@{recipe.title}"

                    android:textColor="#000"
                    android:textSize="@dimen/recipe_title_text_size" />

                <LinearLayout
                    android:id="@+id/container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/recipe_title"
                    android:orientation="horizontal"
                    android:padding="10dp"
                    android:weightSum="100">

                    <TextView
                        android:id="@+id/recipe_social_score"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="10"
                        android:gravity="center"
                        android:text="@{String.valueOf(
                                 Math.round(recipe.social_rank))}"
                        android:textColor="@color/red"

                        android:textSize="@dimen/
                            recipe_publisher_text_size"/>
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/ingredients_container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/container"
                    android:orientation="vertical"
                    android:padding="10dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@{StringUtils.getStringIngredients(
                                          recipe.ingredients)}" />
                </LinearLayout>
            </RelativeLayout>
        </ScrollView>
    </layout>

_BaseActivity布局 "activity_base"

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/base_relative_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/activity_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </FrameLayout>

    <ProgressBar
        android:id="@+id/progress_bar"
        style="@style/Widget.AppCompat.ProgressBar"
        android:layout_width="125dp"
        android:layout_height="125dp"
        android:layout_centerInParent="true"
        android:visibility="gone" />

</RelativeLayout>

使用数据绑定的_BaseActivity "第二种方式"

public abstract class BaseActivity extends AppCompatActivity {
public ProgressBar mProgressBar;
public ActivityBaseBinding baseBinding;

@Override
public void setContentView(int layoutResID) {

      baseBinding = DataBindingUtil.inflate(
            getLayoutInflater(), R.layout.activity_base,  null, false);
      mProgressBar = baseBinding.progressBar;

    /**
     * True means layoutResID should be inflated and made a part of the 
                      parent frameLayout
     */
    getLayoutInflater().inflate(layoutResID, baseBinding.activityContent, 
                                                                      true);
    super.setContentView(baseBinding.getRoot());
}

public void showProgressBar(boolean visibility){
    mProgressBar.setVisibility(visibility ?
                       View.VISIBLE : View.INVISIBLE);
}
1个回答

2
在充气后调整布局以适应充气后所做的更改,请调用layout.requestLayout()
 getLayoutInflater().inflate(layoutResID, baseBinding.activityContent, true);
 mRelativeLayout.requestLayout();
 super.setContentView(baseBinding.getRoot());
public void requestLayout ()
当某些内容已更改并使此视图的布局无效时,请调用此方法。这将安排对视图树进行布局传递。
如果您在调试过程中可以看到视图层次结构中的子项,则应该可以解决此问题。

https://developer.android.com/reference/android/view/View.html#requestLayout()

第二部分: 绑定不起作用

您正在两次填充视图,一次在子活动中,一次在您的BaseActivity中:

  mBinding = DataBindingUtil.inflate(
                getLayoutInflater(), 
                R.layout.activity_recipe, null, false);
    setContentView(R.layout.activity_recipe);

您已经使用数据绑定进行了一次填充,然后将布局ID传递给setContentView,在那里它再次被填充:

 getLayoutInflater().inflate(layoutResID, frameLayout, true);

因此,在数据绑定中的那个视图与您添加到基本布局的那个不同。

创建一个重载版本的setContentView,接受视图而不是ID。


1
谢谢,我刚试了一下,但是没有成功。实际上,我能够看到充气布局作为帧布局的子项,但由于某种原因,数据绑定在其中无法工作。 - Mustafa Shahoud
1
@MustafaShahoud 我注意到它不起作用,我以为你会找出原因,你正在两次膨胀子活动。 - Zohaib Amir
1
这是绝对正确的,我也考虑过这个问题。但我必须膨胀第一次才能设置数据绑定变量,而且实际上我不知道如何将 mBinding 膨胀到 frameLayout 中。我可以在基本活动中扩展 setContentView 来接受两种传递参数类型,然后我就能传递 mBinding.getRoot() 了,但如何将其膨胀到 frameLayout 呢? - Mustafa Shahoud
调用 mRelativeLayout.addView(inflatedViewFromParameter, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)) - Zohaib Amir
2
@ Zohaib Amir 谢谢兄弟,你让我今晚很开心。我已经接受了你的答案并点赞了它。 - Mustafa Shahoud
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接