Android:带有片段的模板模式

Posted

技术标签:

【中文标题】Android:带有片段的模板模式【英文标题】:Android: template pattern with fragments 【发布时间】:2017-02-19 12:09:30 【问题描述】:

这应该是一个简单的问题,但由于某种原因,我遇到了麻烦。假设我有一个 FragmentOne 和 FragmentTwo。 FragmentOne 看起来像这样:

private static final String PATH_KEY = "path_key";

private Asset asset;

public FragmentOne() 
    // Required empty public constructor



public static FragmentOne newInstance(Asset asset) 
    FragmentOne fragment = new FragmentOne();
    Bundle args = new Bundle();
    args.putSerializable(PATH_KEY, asset);
    fragment.setArguments(args);
    return fragment;


@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    if (getArguments() != null) 
        asset = (Asset) getArguments().getSerializable(PATH_KEY);
    


@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
        final Bundle savedInstanceState) 
    final FragmentOneBinding binding = DataBindingUtil
            .inflate(inflater, R.layout.fragment_video, container, false);
    bindAsset(binding, asset);
    return binding.getRoot();


public void bindAsset(FragmentOneBinding binding, Asset asset) 
    binding.textView.setText("FragOne displays asset like this " + asset.text);
    //this is the only method which differs from FragmentTwo


而 FragmentTwo 看起来像这样:

private static final String PATH_KEY = "path_key";

private Asset asset;

public FragmentTwo() 
    // Required empty public constructor



public static FragmentTwo newInstance(Asset asset) 
    FragmentTwo fragment = new FragmentTwo();
    Bundle args = new Bundle();
    args.putSerializable(PATH_KEY, asset);
    fragment.setArguments(args);
    return fragment;


@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    if (getArguments() != null) 
        asset = (Asset) getArguments().getSerializable(PATH_KEY);
    


@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
        final Bundle savedInstanceState) 
    final FragmentTwoBinding binding = DataBindingUtil
            .inflate(inflater, R.layout.fragment_video, container, false);
    bindAsset(binding, asset);
    return binding.getRoot();


public void bindAsset(FragmentOneBinding binding, Asset asset) 
    binding.textView.setText("But FragTwo, which is very different, displays asset like this " + asset.image.getName());
    //this is the only method which differs from FragmentOne


如您所见,在两个片段中,newInstance、onCreate 和 onCreateView 方法在结构上是相同的。唯一真正的区别是两个片段的onCreateView内部调用的bindView方法不一样。

使用泛型、抽象类、接口或某种组合,我可以将事情简化为模板设计模式吗?这样下次我想制作具有完全相同结构的片段时,我可以做一些这样的事情吗?

class FragmentThree extends TemplateFragment 

    @Override
    public void bindAsset(FragmentThreeBinding binding, Asset asset)
        binding.textView.setText(asset.name);
    


我已经尝试过创建一个抽象类,但是抽象类中不能有静态方法,所以 newInstance() 在这里阻止了我。我也尝试了几种实现接口的方法,但没有任何运气。

【问题讨论】:

【参考方案1】:

我认为您尝试的抽象类是正确的方法。您仍然需要将newInstance() 放在每个具体子类中,不仅因为它是静态的,还因为它需要知道要实例化的具体类型。

【讨论】:

您好。你是对的,采用你的方法确实在某种程度上简化了代码,尽管没有我希望的那么多。我会接受你的回答。但是,如果我还需要考虑 newInstance 部分,您有什么建议?某种工厂类? (在我的例子中,FragmentOne、FragmentTwo 和 Fragment 3 都在不同的 FragmentSwitcher 类中实例化,除了要切换到的片段类型之外,它们在功能上也都是相同的。最好将它们简化为单个通用切换器类)。 这个 FragmentSwitcher 类是创建同一个片段类的多个实例还是可以与单个实例一起工作? @ike 理想情况下,您应该发布一个带有此问题链接的新问题。【参考方案2】:

抽象方法不能使用 static 。 工厂模式以创建类实例化。 Fragment 使用工厂模式,本身添加静态方法。

【讨论】:

以上是关于Android:带有片段的模板模式的主要内容,如果未能解决你的问题,请参考以下文章

使用带有附加类型参数的奇怪重复模板模式 (CRTP)

设计模式与Android模板方法模式——照葫芦画瓢

Android 设计模式-->模板方法模式

《Android源码设计模式》--模板方法模式

3.模板模式

小白自我提高学习设计模式笔记—模板模式