Android getSupportFragmentManager().findFragmentById()返回null,即使片段存在
我在Android getSupportFragmentManager().findFragmentById()返回null,即使片段存在,android,android-fragments,Android,Android Fragments,我在活动\u main.xml中有一个片段\u main.xml 该片段添加在从Android Studio模板创建的选项卡式活动中 我想从活动中更改片段的视图。这就是为什么我创建了一个接口,当我知道片段的视图可以修改时,该接口允许片段在片段的启动过程中调用活动 如果我使用我的接口回调传递实际的片段实例,那么我确实实现了这一点。但我仍然感到沮丧,因为我不明白为什么这个函数返回null。这是否与在不同的屏幕方向上重用片段有关 我已经在这里查看了类似的问题,所以这个函数返回null。有人提到使用im
活动\u main.xml
中有一个片段\u main.xml
该片段添加在从Android Studio模板创建的选项卡式活动中
我想从活动中更改片段的视图。这就是为什么我创建了一个接口,当我知道片段的视图可以修改时,该接口允许片段在片段的启动过程中调用活动
如果我使用我的接口回调传递实际的片段实例,那么我确实实现了这一点。但我仍然感到沮丧,因为我不明白为什么这个函数返回null。这是否与在不同的屏幕方向上重用片段有关
我已经在这里查看了类似的问题,所以这个函数返回null。有人提到使用import android.support.v4.app.Fragment可能有问题
而不是android.app.Fragment。我不认为这是我的情况,因为getsupportFragmentManager似乎返回了正确类型的片段(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>
我会尝试以下方法,但我肯定这不是最好的解决方案 我将传递
section\u number
的值,而不是占位符片段
,并从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);
}
首先,您使用了
findFragmentById
错误,将片段根布局的id
作为参数传递,而它需要包含片段的布局的id
(而不是片段内部的布局!)
FragmentPagerAdapter有点棘手,获取当前片段并不简单。检查以下答案:
替换您的:
PlaceholderFragment fragment = (PlaceholderFragment)(getSupportFragmentManager().findFragmentById(R.id.main_audio_view));
//FRAGMENT IS NULL!
与
我懂了!谢谢:)。这看起来有点。。。就像你说的,很棘手。我想通过函数调用将实例本身作为参数传递会更干净?有什么反对这样做的建议吗?为什么有人会使用这种方式而不是将片段实例传递回活动?一次性传递片段实例是可以的,但是将该实例保存在字段中是不可靠的,因为
FragmentManager
可能会在屏幕上重新创建片段旋转或其他状态
更改。我发布的代码片段更适合您需要更新当前显示的片段,但您没有它的实例。谢谢:)。就命名约定(“android:switcher”…等)而言,findFragmentByTag是否“稳定”在各个版本中保持一致?是否有更好的方法获取/保存碎片?我想知道为什么我不能在片段中获得视图(TextView),比如说view\u id.fragment\u id.view\u id为什么我不能给片段附加一个id?
PlaceholderFragment page = (PlaceholderFragment)
getSupportFragmentManager().findFragmentByTag("android:switcher:" +
R.id.container + ":" + mViewPager.getCurrentItem());