Search code examples
androidandroid-custom-viewmvp

Not able to pass a object to my custom compound control


I am using MVP for my Android project. I have an POJO Product and need to be able to show the details of this product in a separate activity. This can activity needs 2 different layout: 1. a layout with a button to print the details of this product 2. a layout with 2 buttons to add the selected product to a wishlist or cancel the action

Both above described layouts have the same xml layout to display the details so I want to make a compound component, like desbribed here

I want to implement this with the MVP architecture. So my goals is that I have a class which extends ConstraintLayout and serves as my view. The view has it own presenter to set the TextView s with the data from the Product.

All of this works, but I am not able to pass the selected Product from the presenter of the activity that has the compound component, which results that the data of the product is not shown in the compound.

the DetailCompound.java

public class DetailsCompound extends ConstraintLayout {
    TextView productTv, brandTv, sizeTv, extraTv, materialTv, familyTv;
    ImageView codeImg;
    DetailPresenter presenter;

    public DetailsCompound(Context context, Product product) {
        super(context);
        this.initViews(context);
        this.createPresenter(product);
    }

    private void initViews(Context context) {
        inflate(this.getContext(), R.layout.product_details, this);

        //initialize views
    }

    private void createPresenter(Product product) {
        this.presenter = new DetailPresenter(this, product);
    }
}

the DetailPresenter.java

public class DetailPresenter implements OnLoadListener {
    DetailsCompound compound;
    StorageManager storage;
    Product product;

    public DetailPresenter(DetailsCompound compound, Product product) {
        this.compound = compound;
        this.storage = new StorageManager();
        this.storage.setOnLoadListener(this);
        this.setProduct(product);
    }

    private void setProduct(Product product) {
        this.product = product;

        //set details of product in view

        this.storage.getProductCodeImage(this.product.getCodeUrl());
    }

    @Override
    public void onLoad(Object loadedObj) {
        this.compound.codeImg.setImageBitmap((Bitmap) loadedObj);
    }
}

the activity_product_detail.xml which includes the compound

<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:id="@+id/linearLayout2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:paddingHorizontal="8dp"
    tools:context=".productdetail.ProductDetailActivity">

    <include
        android:id="@+id/product_details"
        layout="@layout/product_details"
        android:layout_width="395dp"
        android:layout_height="534dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/print_btn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/print_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Print"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

the ProductDetailActivity.java

public class ProductDetailActivity extends AppCompatActivity {
    Button printBtn;

    DetailsCompound productDetails;
    ProductDetailPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_product_detail);

        createPresenter();
        initViews();
    }

    private void initViews() {
        this.productDetails = new DetailsCompound(this.getApplicationContext(), this.presenter.product);
        printBtn = (Button)findViewById(R.id.print_btn);
    }

    private void createPresenter() {
        this.presenter = new ProductDetailPresenter(this);
    }
}

I don't have a clue how to "link" the <include> in the activity_product_detail.xml with the DetailCompound.java


Solution

  • So, I figured it out...

    My logic was great, but I just didn't know how to use a compound component. Here's how I fixed it:

    the activity_product_detail.xml which implements the compound:

    <androidx.constraintlayout.widget.ConstraintLayout 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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:paddingHorizontal="8dp">
    
        <com.example.imanager.compounds.details.DetailsCompound
            android:id="@+id/product_details"
            android:layout_width="395dp"
            android:layout_height="534dp"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toTopOf="@+id/print_btn"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <Button
            android:id="@+id/print_btn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Print"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    It didn't work because I used an <include> tag instead of implementing the compound java class itself. In this java class the inflater is used to inflate the reusable UI component:

    private void initViews() {
            LayoutInflater.from(getContext()).inflate(R.layout.compound_product_details, this);
    
            //init views
        }
    

    In the activity, ProductDetailActivity.java, that holds the compound we just instantiate the compound doing this:

    this.productDetails = (DetailsCompound)findViewById(R.id.product_details);
            this.productDetails.getPresenter().setProduct(this.presenter.product);