getSupportFragmentManager()。findFragmentById()即使存在片段也返回null

时间:2017-05-15 14:27:01

标签: android android-fragments

我在fragment_main.xml内有activity_main.xml

片段添加在从Android Studio模板创建的选项卡式活动中。

我想在活动中对Fragment的视图进行更改。这就是为什么我创建了一个界面,允许片段在片段 onStart 期间调用Activity,当我知道Fragment的视图可用于修改时。

如果我使用我的接口回调传递实际的Fragment实例,我确实能够正常工作。但我仍然感到沮丧,因为我不明白为什么这个函数返回null。这与在不同屏幕方向重用片段有什么关系吗?

我已经通过此函数返回null来查看SO报告的类似问题。有人提到使用import android.support.v4.app.Fragment;而不是android.app.Fragment可能存在问题。我不认为这是我的情况,因为获取支持 FragmentManager似乎返回正确类型的Fragment(v4.app)。我不知道为什么v4.app在那里,我对这一切都不熟悉。

无论如何,这里的所有代码,包括进口代码,因为它们可能是相关的。

package org.axonnsd.musicnexus;

import android.app.Activity;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import android.widget.MediaController;
import android.widget.TextView;

import java.io.FileInputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity implements OnFragmentReadyListener {

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private SectionsPagerAdapter mSectionsPagerAdapter;

    private static final String TAG = "MyTabbedApplication";

    private Handler handler = new Handler();

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;

    @Override
    protected void onStop() {
        super.onStop();
        mediaController.hide();
        mediaPlayer.stop();
        mediaPlayer.release();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //the MediaController will hide after 3 seconds - tap the screen to make it appear again
        mediaController.show();
        return false;
    }


    public void onFragmentReady(PlaceholderFragment fragment)
    {
        this.getIntent().putExtra(AUDIO_FILE_NAME,AUDIO_FILE_NAME);
        audioFile = this.getIntent().getStringExtra(AUDIO_FILE_NAME);

        PlaceholderFragment fragment = (PlaceholderFragment)(getSupportFragmentManager().findFragmentById(R.id.main_audio_view));
                //FRAGMENT IS NULL!
        fragment.setNowPlayingText(audioFile);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String ARG_SECTION_NUMBER = "section_number";
        private TextView _txtNowPlaying;
        private MainActivity _parentActivity;

        public PlaceholderFragment() {
        }

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            TextView textView = (TextView) rootView.findViewById(R.id.section_label);
            _txtNowPlaying = (TextView)rootView.findViewById(R.id.now_playing_text);
            textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
            //notifyActivity(_parentActivity);
            return rootView;
        }

        @Override
        public void onAttach(Activity activity)
        {
            super.onAttach(activity);
            _parentActivity = (MainActivity)activity;
        }

        @Override
        public void onAttach(Context context)
        {
            super.onAttach(context);

            if (context instanceof Activity){
                _parentActivity = (MainActivity)context;
            }
        }

        @Override
        public void onStart()
        {
            super.onStart();
            notifyActivity(_parentActivity);
        }

        private void notifyActivity(MainActivity activity)
        {
            activity.onFragmentReady(this);
        }

        public void setNowPlayingText(String value)
        {
            _txtNowPlaying.setText(value);
        }
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            return PlaceholderFragment.newInstance(position + 1);
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "SECTION 1";
                case 1:
                    return "SECTION 2";
                case 2:
                    return "SECTION 3";
            }
            return null;
        }
    }
}

我也粘贴了XML,即使它们很好(正如我所说,如果我传递实际的片段,它也能正常工作)。

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="org.axonnsd.musicnexus.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/AppTheme.PopupOverlay">

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

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

fragment_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/main_audio_view"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="org.axonnsd.musicnexus.MainActivity$PlaceholderFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Now playing:"
        android:textSize="25sp"
        android:textStyle="bold"
        />
    <TextView
        android:id="@+id/now_playing_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:layout_marginLeft="10dip"
        android:layout_marginRight="10dip"
        android:layout_gravity="center"
        android:text="Now playing.."
        android:textSize="16sp"
        android:textStyle="italic"
        />

    <TextView
        android:id="@+id/section_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

2 个答案:

答案 0 :(得分:1)

首先,当您希望片段的findFragmentById包含id时,您使用id错误,将片段的根布局PlaceholderFragment fragment = (PlaceholderFragment)(getSupportFragmentManager().findFragmentById(R.id.main_audio_view)); //FRAGMENT IS NULL! 作为参数传递你的片段(不是片段内的布局!)

FragmentPagerAdapter有点棘手,获取当前片段并不简单。检查这个答案: Getting the current Fragment instance in the viewpager

替换你的:

PlaceholderFragment page = (PlaceholderFragment) 
getSupportFragmentManager().findFragmentByTag("android:switcher:" + 
R.id.container + ":" + mViewPager.getCurrentItem());

<time>

答案 1 :(得分:0)

我会尝试以下方法,但我确定这不是最好的解决方案。

我会传递section_number的值而不是PlaceholderFragment,并从SectionPageAdapter获取片段。像这样:

 public void onFragmentReady(int position)
 {
    this.getIntent().putExtra(AUDIO_FILE_NAME,AUDIO_FILE_NAME);
    audioFile = this.getIntent().getStringExtra(AUDIO_FILE_NAME);

    PlaceholderFragment fragment = (PlaceholderFragment)mSectionsPagerAdapter.getItem(position);

    fragment.setNowPlayingText(audioFile);
 }