【问题标题】:Instantiate Fragment dynamically by class name按类名动态实例化 Fragment
【发布时间】:2014-10-09 15:46:48
【问题描述】:

我有一个带有菜单的主要活动来浏览页面。为了使我的代码动态化,我使用所有片段的名称和类创建了适配器。

public class MenuItem {

    private String title;
    private Class className;
    ...
}

我的适配器是这样创建的:

    ArrayList<MenuItem> menuItems=new ArrayList<MenuItem>();

    menuItems.add(new MenuItem("Home", null, HomeFragment.class, R.drawable.ic_drawer, true));
    menuItems.add(new MenuItem("Schedule", null, ScheduleFragment.class, R.drawable.ic_drawer, false));

在我的onClickListener菜单中,我想直接打开页面而不做任何条件语句:

private AdapterView.OnItemClickListener mItemClickListener = new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        Class c =  ((MenuItem) mMenuAdapter.getItem(position)).getClassName();
        Fragment fragment = ??? //How do I create a Fragment dynamically ? 

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.fl_container, fragment).commit();

这种编码方式用于 Activity,但在这种情况下更简单,因为要更改 Activity,我们只使用带有 Activity 名称的 startActivity,而不是它的实例。

我需要使用反射吗?

【问题讨论】:

    标签: java android list class fragment


    【解决方案1】:

    只需调用Class#newInstance() 方法:

    Fragment fragment = c.newInstance();
    

    确保您的 Fragment 类具有默认构造函数。

    您还需要将此构造包装到 try-catch 子句中,因为 newInstance() 会引发几个异常 - InstantiationExceptionIllegalArgumentException

    【讨论】:

    • 已经试过了:它会抛出 java.lang.InstantiationException
    • 异常消息中的内容是什么? 编辑: 来自文档 - 如果此 Class 表示抽象类、接口、数组类、原始类型或 void,则会引发 InstantiationException;或者如果该类没有空构造函数;或者如果由于其他原因实例化失败。我想你的片段没有无参数构造函数。
    • 我错过了 try catch + cast
    • 另外,您可以保留类名,并使用Fragment.instantiate(String classname) 创建新实例,而不是缓存实际的类。
    • @kcoppock 很有趣,不知道这个。 instantiate() 没有单参数版本,但我们还需要传递 Context 实例。
    猜你喜欢
    • 2014-01-26
    • 2019-11-08
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多