无法访问片段内的Textview

时间:2017-01-05 05:23:27

标签: android android-layout android-studio android-fragments textview

我有一个带有片段的活动,里面有一个TextView。在CourseFragment.java中,我创建了一个简单的方法来更改TextView的文本。但是,当我尝试从Activity调用片段的方法时,它表示TextView对象为null。以下是我的一些代码:

CourseFragment.java

public class CourseFragment extends Fragment {

private Subject subject;
View rootView;
private TextView title;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    rootView = inflater.inflate(R.layout.fragment_course, container,
            false);

    title = (TextView) rootView.findViewById(R.id.course_title);

    return rootView;
}

public void setTitle() {
    title.setText("My Title");
}

}

这是我的活动中的代码,它使新片段放入正确的位置:

CourseFragment fragment = new CourseFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.course1, fragment);
fragment.setTitle();
ft.addToBackStack(null);
ft.commit();

来自片段

内的setTitle()方法的错误
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

这似乎很直接,但我不明白为什么我会继续获得NPE。我查看了类似的问题并尝试了所有可接受的解决方案但无济于事。任何想法?

提前致谢

编辑:根据要求,这里还有一些代码:

fragment_course.xml

的开头
<LinearLayout 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/course_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.stagenda.stagenda.CourseFragment"
    android:padding="16dp"
    android:orientation="vertical"
    android:background="@android:color/background_light">

    <RelativeLayout
        android:layout_width="match_parent"
        tools:ignore="UselessParent"
        android:background="@color/colorAccent"
        android:padding="16dp"
        android:layout_height="wrap_content"
        android:id="@+id/course_container">
<TextView
        android:text="Course Given Title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/course_given_title"
        android:textColor="@android:color/background_light"
        android:textSize="18sp" />

    <TextView
    android:text="Course Title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/course_title"
    android:layout_below="@+id/course_given_title"
    android:textColor="@android:color/background_light" />

    <TextView
        android:text="Course Code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/course_code"
        android:textColor="@android:color/background_light"
        android:layout_toRightOf="@+id/course_title"
        android:layout_below="@+id/course_given_title"
        android:layout_alignParentEnd="false"
        android:layout_marginStart="10dp" />

完整错误:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.stagenda.stagenda, PID: 1654
                  java.lang.IllegalStateException: Could not execute method for android:onClick
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                      at android.view.View.performClick(View.java:5639)
                      at android.view.View$PerformClick.run(View.java:22387)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6088)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Method.invoke(Native Method)
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                      at android.view.View.performClick(View.java:5639) 
                      at android.view.View$PerformClick.run(View.java:22387) 
                      at android.os.Handler.handleCallback(Handler.java:751) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6088) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                      at com.stagenda.stagenda.CourseFragment.setTitle(CourseFragment.java:34)
                      at com.stagenda.stagenda.MainPage.confirmAddCourse(MainPage.java:435)
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                      at android.view.View.performClick(View.java:5639) 
                      at android.view.View$PerformClick.run(View.java:22387) 
                      at android.os.Handler.handleCallback(Handler.java:751) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6088) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
I/Process: Sending signal. PID: 1654 SIG: 9
Disconnected from the target VM, address: 'localhost:8612', transport: 'socket'

explanation of layout (image)

7 个答案:

答案 0 :(得分:2)

使用这个approch。

 Bundle bundle = new Bundle();
    bundle.putString("title", "whatever you want to pass");

        CourseFragment fragment = new CourseFragment();
        fragment.setArguments(bundle);
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.course1, fragment);
        ft.addToBackStack(null);
        ft.commit();



    public class CourseFragment extends Fragment {

    private Subject subject;
    View rootView;
    private TextView title;
    Bundle bundle;

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

            bundle = getArguments();
         }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        rootView = inflater.inflate(R.layout.fragment_course, container,
                false);

        title = (TextView) rootView.findViewById(R.id.course_title);

        String text = bundle.getString("title");
        title.setText(text);

        return rootView;
    }


    }

答案 1 :(得分:1)

我自己想通了。问题出在这里:

CourseFragment fragment = new CourseFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.course1, fragment);
fragment.setTitle();
ft.addToBackStack(null);
ft.commit();

问题是我在没有创建视图的片段上调用setTitle()。相反,当我做了以下问题时,问题就解决了:

CourseFragment fragment = new CourseFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.course1, fragment);
ft.addToBackStack(null);
ft.commit();

CourseFragment frag = fm.findFragmentById(R.id.course1);
frag.setTitle();

我最终改变了很多代码,但我希望这有助于某人。感谢大家的答案

答案 2 :(得分:0)

您可以做的一件事是将数据作为参数传递:

CourseFragment fragment = new CourseFragment(Your title);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.course1, fragment);
ft.addToBackStack(null);
ft.commit();

您还可以使用捆绑来传递数据。

答案 3 :(得分:0)

片段事务不是同步的。当你添加一个事务时,它可以在主循环器有机会运行它时执行(它会排队等待以后)。

这意味着片段会在当前方法结束之后才会附加。检查执行CourseFragment.setTitle()onCreateView()的顺序。

请参阅FragmentTransaction.commit()的文档:commit

如果适用于您,请考虑使用commitNow()

另外,请考虑将标题作为参数传递给片段,以便可以使用onCreateViewgetArguments()内阅读。

答案 4 :(得分:0)

标签布局:

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:background="#ffffff">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways"
            app:layout_collapseMode="pin"
            android:background="#000000"
            app:titleTextColor="#ffffff"

            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/PopupMenuStyle">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:id="@+id/textview"
                android:textColor="@color/colorTrueWhite"/>

        </android.support.v7.widget.Toolbar>

        <!-- our tablayout to display tabs  -->
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorBlack"
            android:minHeight="?attr/actionBarSize"

            app:tabIndicatorColor="@color/colorTrueWhite"
            app:tabIndicatorHeight="5dp"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

        <!-- View pager to swipe views -->


        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="fill_parent"/>


    </LinearLayout>

使用该布局的活动:

public class Main2Activity extends AppCompatActivity implements TabLayout.OnTabSelectedListener {

    private TabLayout tabLayout;
    public static ViewPager viewPager;
    public static Context ctx;
    Pager adapter;
    public static int expired, paid;
    Boolean isConnection;

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

        Toolbar tb = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(tb);

        TextView tv = (TextView) findViewById(R.id.textview);

        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);


        ctx = getApplicationContext();


        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);


        tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        viewPager = (ViewPager) findViewById(R.id.pager);


        tabLayout.addTab(tabLayout.newTab().setText("title1"));
        tabLayout.addTab(tabLayout.newTab().setText("title2"));
        tabLayout.addTab(tabLayout.newTab().setText("title3"));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        tabLayout.setupWithViewPager(viewPager);

        adapter = new Pager(getSupportFragmentManager(), tabLayout.getTabCount(), ctx);
        viewPager.setAdapter(adapter);


        if(some condition)
        {
            viewPager.setCurrentItem(2);
        }
        else
        {
            viewPager.setCurrentItem(1);
        }
        viewPager.setOffscreenPageLimit(2);

        tabLayout.addOnTabSelectedListener(this);

        ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
        int tabsCount = vg.getChildCount();
        for (int j = 0; j < tabsCount; j++) {
            ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
            int tabChildsCount = vgTab.getChildCount();
            for (int i = 0; i < tabChildsCount; i++) {
                View tabViewChild = vgTab.getChildAt(i);
                if (tabViewChild instanceof TextView) {
                    ((TextView) tabViewChild).setTypeface(Typeface.DEFAULT, Typeface.BOLD);
                }
            }
        }
    }


    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        viewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
    }


}

寻呼机代码:

public class Pager extends FragmentStatePagerAdapter
{
    int tabcount;
    Context ctx;
    private String [] Titles = {"title1", "title2", "title3"};

    public Pager(FragmentManager fm, int tabcount, Context ctx)
    {
        super(fm);
        this.tabcount = tabcount;
        this.ctx = ctx;
    }

    @Override
    public int getCount() {
        return tabcount;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return Titles[position];
    }

    @Override
    public Fragment getItem(int position) {

        switch (position) {

            case 0:
                Tab1 tab1 = new Tab1();
                return tab1;

            case 1:
                Tab2 tab2 = new Tab2();
                return tab2;

            case 2:
                Tab3 tab3 = new Tab3();
                return tab3;

            default:
                return null;
        }
    }


}

答案 5 :(得分:0)

使用 Framgnet Callbacks 解决了这个问题,如http://developer.android.com/training/basics/fragments/communicating.html所述。我相信这是最好的方法是在创建片段后将TextViews传递给我的活动。

答案 6 :(得分:0)

fragmentTransaction.commit()之后调用 onCreateView()方法。 因为,您在 fragmentTransaction.commit()之前调用 setTitle(),所以TextView实例 title 未实例化,因此为null。 在 fragmentTransaction.commit()之后添加 fragment.setTitle()行。