2022年10月20日 星期四

[Android] 使用ViewBinding建立BaseFragment

先在build.gradle內開啟viewBinding。

    buildFeatures{
        viewBinding true
        dataBinding true
    }

開啟後在res->layout內創建一個layout(my_fragment.xml),
Android會自動生成一個類名稱與layout名字相同的viewBinding(MyFragmentBinding),
可以使用下面的程式碼產生view。

public class MyFragment extends Fragment {
    MyFragmentBinding viewBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        viewBinding = MyFragmentBinding.inflate(inflater, container, false);
        return viewBinding.getRoot();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        viewBinding = null;
    }
}

但當Fragment很多時,每創建一個就必須寫重復的程式碼,所以可以把重復的程式碼提取到一個父類別,每個Fragment之間的差別只有在 viewBinding的類不同,但都是繼承ViewBinding,所以可以使用泛型的方式,告訴父類別在子類別中的ViewBinding是什麼類別名稱,將父類別設成abstract,再設定abstract方法取得子類別的viewBinding物件。

public abstract class BaseFragment<V extends Viewbinding> extends Fragment {
    public V viewBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        viewBinding = getBindingInflater().invoke(inflater, container, savedInstanceState);
        return viewBinding.getRoot();
    }
    
    //取得子類的viewBinding物件
    public abstract Function3<LayoutInflater, ViewGroup, Bundle, V> getBindingInflater();

    @Override
    public void onDestroy() {
        super.onDestroy();
        viewBinding = null;
    }
}

在MyFragment中只要告訴BaseFragment子類別的viewBinding是什麼類別(MyFragmentBinding),再將viewBinding透過實作方法回傳給父類別即可。

public class MyFragment extends BaseFragment<MyFragmentBinding> {
    MyFragmentBinding viewBinding;
    
    @Override
    public Function3<LayoutInflater, ViewGroup, Bundle, MyFragmentBinding> getBindingInflater() {
        return (o1,o2,o3)->MyFragmentBinding.inflate(o1,o2,false);
    }
}

Funtion3也可與以下Get方法相同,最大的差別是Funtion3可用lambda表達式。

public abstract V getBindingInflater(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
public abstract Function3<LayoutInflater, ViewGroup, Bundle, V> getBindingInflater();

沒有留言:

張貼留言