java片段选项卡未附加到上下文
我目前正在安卓 studio上制作一个音板应用程序,其中有大量的片段。选项卡布局上的第一个页面只是一个普通的按钮视图,但第二个选项卡视图中有另一个片段视图。目标是第一个页面只显示一些正常的声音,第二个选项卡有多个操作员为其选择特定的音板
不管怎样,这个应用程序似乎运行良好。我可以从主选项卡切换到operator选项卡,甚至可以选择operator soundboard页面并移动到它们的片段。但是,当我尝试切换片段(通过我的tabview)时,我的应用程序崩溃,并出现错误:
"Fragment operatorTab{4623fc9} (312d4e58-458c-4f47-8fa3-794fe15f0536)} not attached to a context."**
**at com.jkcarraher.rainbowsixsoundboard.operatorTab.resetAllButtons(operatorTab.java:113)
at com.jkcarraher.rainbowsixsoundboard.operatorTab.access$000(operatorTab.java:31)
at com.jkcarraher.rainbowsixsoundboard.operatorTab$2.onScrollChanged(operatorTab.java:107)
我在下面附上了我的代码,如果你有任何想法,请告诉我
主要活动。java
import 安卓.graphics.Color;
import 安卓.os.Bundle;
import 安卓.text.SpannableString;
import 安卓.text.Spanned;
import 安卓.text.style.ForegroundColorSpan;
import 安卓.widget.Adapter;
import 安卓.widget.TextView;
import com.google.安卓.gms.ads.MobileAds;
import com.google.安卓.gms.ads.initialization.InitializationStatus;
import com.google.安卓.gms.ads.initialization.OnInitializationCompleteListener;
import com.google.安卓.material.tabs.TabLayout;
import 安卓x.viewpager.widget.ViewPager;
import 安卓x.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private SectionsPageAdapter mSectionsPageAdapter;
private ViewPager mViewPager;
private TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeAds();
makeSixYellow();
//Create ViewPager (that houses all fragments)
mSectionsPageAdapter = new SectionsPageAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
setUpViewPager(mViewPager);
//Add & customize tabs
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setTabTextColors(Color.WHITE, Color.WHITE);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setText("Utility");
tabLayout.getTabAt(1).setText("Voice Lines");
checkPageChange();
}
private void setUpViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new SectionsPageAdapter(getSupportFragmentManager());
adapter.addFragment(new utilityTab(), "Utility");
adapter.addFragment(new voiceLinesView(), "Voice Lines");
viewPager.setAdapter(adapter);
}
private void makeSixYellow(){
TextView textView = findViewById(R.id.titleText);
String text = "R6 Soundboard";
SpannableString ss = new SpannableString(text);
ForegroundColorSpan fcsYellow = new ForegroundColorSpan(Color.rgb(255,236,141));
ss.setSpan(fcsYellow, 1,2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
}
private void initializeAds(){
MobileAds.initialize(this, new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
}
});
}
private void checkPageChange(){
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
utilityTab.resetAllButtons();
}
@Override
public void onPageSelected(int position) {
utilityTab.resetAllButtons();
}
@Override
public void onPageScrollStateChanged(int state) {
utilityTab.resetAllButtons();
}
});
}
}
主要活动。xml
<?xml version="1.0" encoding="utf-8"?>
<安卓x.coordinatorlayout.widget.CoordinatorLayout
xmlns:安卓="http://schemas.安卓.com/apk/res/安卓"
xmlns:app="http://schemas.安卓.com/apk/res-auto"
xmlns:tools="http://schemas.安卓.com/tools"
安卓:layout_width="match_parent"
安卓:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.安卓.material.appbar.AppBarLayout
安卓:layout_width="match_parent"
安卓:layout_height="wrap_content"
安卓:background="@color/colorHeader"
安卓:theme="@style/AppTheme.AppBarOverlay">
<TextView
安卓:id="@+id/titleText"
安卓:layout_marginLeft="20dp"
安卓:layout_marginTop="20dp"
安卓:layout_width="wrap_content"
安卓:layout_height="wrap_content"
安卓:fontFamily="@font/avenir"
安卓:gravity="center_horizontal"
安卓:text="R6 Soundboard"
安卓:textColor="#FFF"
安卓:textSize="30sp" />
<com.google.安卓.material.tabs.TabLayout
安卓:id="@+id/tabs"
安卓:layout_width="match_parent"
安卓:layout_height="wrap_content"
app:tabTextColor="#fff"
安卓:background="@color/colorHeader" />
</com.google.安卓.material.appbar.AppBarLayout>
<安卓x.viewpager.widget.ViewPager
安卓:id="@+id/view_pager"
安卓:layout_width="match_parent"
安卓:layout_height="match_parent"
安卓:background="@color/colorBody"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</安卓x.coordinatorlayout.widget.CoordinatorLayout>
语音线路视图。java(包含片段,因此我可以选择一个操作符,它将带我到他们的音板片段)
package com.jkcarraher.rainbowsixsoundboard;
import 安卓.os.Bundle;
import 安卓x.fragment.app.Fragment;
import 安卓x.fragment.app.FragmentTransaction;
import 安卓x.viewpager.widget.ViewPager;
import 安卓.view.LayoutInflater;
import 安卓.view.View;
import 安卓.view.ViewGroup;
import com.google.安卓.material.tabs.TabLayout;
public class voiceLinesView extends Fragment {
private SectionsPageAdapter voiceLinesSectionsPageAdapter;
private ViewPager voiceLinesViewPager;
public voiceLinesView() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_voice_lines_view, container, false);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.voiceLinesFrame, new operatorTab());
fragmentTransaction.commit();
return view;
}
}
片段、声音、线条、视图。xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:安卓="http://schemas.安卓.com/apk/res/安卓"
xmlns:tools="http://schemas.安卓.com/tools"
安卓:layout_width="match_parent"
安卓:layout_height="match_parent"
tools:context=".voiceLinesView">
<FrameLayout
安卓:id="@+id/voiceLinesFrame"
安卓:layout_width="match_parent"
安卓:layout_height="match_parent"/>
</FrameLayout>
运算符选项卡。java
package com.jkcarraher.rainbowsixsoundboard;
import 安卓.annotation.SuppressLint;
import 安卓.content.Context;
import 安卓.graphics.Rect;
import 安卓.media.MediaPlayer;
import 安卓.net.Uri;
import 安卓.os.Bundle;
import 安卓x.annotation.Nullable;
import 安卓x.fragment.app.Fragment;
import 安卓x.fragment.app.FragmentManager;
import 安卓x.fragment.app.FragmentTransaction;
import 安卓.view.LayoutInflater;
import 安卓.view.MotionEvent;
import 安卓.view.View;
import 安卓.view.ViewGroup;
import 安卓.view.ViewTreeObserver;
import 安卓.widget.RelativeLayout;
import 安卓.widget.ScrollView;
import com.google.安卓.gms.ads.AdRequest;
import com.google.安卓.gms.ads.AdView;
import soup.neumorphism.NeumorphCardView;
import soup.neumorphism.ShapeType;
import static 安卓.view.MotionEvent.ACTION_MOVE;
public class operatorTab extends Fragment {
private ScrollView scrollView;
public static RelativeLayout KapkanButton;
public static RelativeLayout GlazButton;
public static RelativeLayout FuzeButton;
public static RelativeLayout TachankaButton;
voiceLinesView voiceLinesView = new voiceLinesView();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_operator_tab, container, false);
//Initialize ScrollView
scrollView = view.findViewById(R.id.operatorScrollView);
//Initialize buttons 1-4
KapkanButton = view.findViewById(R.id.kapkanButton);
GlazButton = view.findViewById(R.id.glazButton);
FuzeButton = view.findViewById(R.id.fuzeButton);
TachankaButton = view.findViewById(R.id.tachankaButton);
//Make buttons 1-6 pressable
initPressableButton(KapkanButton);
initPressableButton(GlazButton);
initPressableButton(FuzeButton);
initPressableButton(TachankaButton);
scrollResetListener();
return view;
}
@SuppressLint("ClickableViewAccessibility")
private void initPressableButton(final RelativeLayout relativeLayout) {
relativeLayout.setBackgroundColor(getResources().getColor(R.color.colorBody));
final Rect r = new Rect();
relativeLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
// get the View's Rect relative to its parent
view.getHitRect(r);
// offset the touch coordinates with the values from r
// to obtain meaningful coordinates
final float x = event.getX() + r.left;
final float y = event.getY() + r.top;
if(event.getAction() == MotionEvent.ACTION_DOWN) {
relativeLayout.setBackgroundColor(getResources().getColor(R.color.colorButtonPressed));
return true;
} else if(event.getAction() == MotionEvent.ACTION_UP) {
if (r.contains((int) x, (int) y)) {
relativeLayout.setBackgroundColor(getResources().getColor(R.color.colorBody));
//On Click Up
FragmentTransaction fr = getFragmentManager().beginTransaction();
fr.replace(R.id.voiceLinesFrame, new kapkanVoiceLines());
fr.commit();
}
}else if(event.getAction() == ACTION_MOVE){
if (!r.contains((int) x, (int) y)) {
relativeLayout.setBackgroundColor(getResources().getColor(R.color.colorBody));
}
return true;
}
return false;
}
});
}
private void scrollResetListener(){
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
resetAllButtons();
}
});
}
public void resetAllButtons(){
KapkanButton.setBackgroundColor(getResources().getColor(R.color.colorBody));
GlazButton.setBackgroundColor(getResources().getColor(R.color.colorBody));
FuzeButton.setBackgroundColor(getResources().getColor(R.color.colorBody));
TachankaButton.setBackgroundColor(getResources().getColor(R.color.colorBody));
}
}
片段操作符选项卡。xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:安卓="http://schemas.安卓.com/apk/res/安卓"
xmlns:tools="http://schemas.安卓.com/tools"
安卓:layout_width="match_parent"
安卓:layout_height="match_parent"
xmlns:app="http://schemas.安卓.com/apk/res-auto"
tools:context=".operatorTab">
<ScrollView
安卓:id="@+id/operatorScrollView"
安卓:layout_width="match_parent"
安卓:layout_height="wrap_content">
<RelativeLayout
安卓:layout_width="match_parent"
安卓:layout_height="wrap_content"
安卓:background="@color/colorBody">
<RelativeLayout
安卓:id="@+id/kapkanButton"
安卓:layout_width="match_parent"
安卓:layout_height="60sp"
安卓:orientation="horizontal">
<ImageView
安卓:id="@+id/kapkanIcon"
安卓:layout_width="50sp"
安卓:layout_height="50sp"
安卓:layout_marginTop="5sp"
安卓:layout_marginLeft="10sp"
安卓:src="@drawable/ic_kapkan"/>
<TextView
安卓:layout_width="wrap_content"
安卓:layout_height="wrap_content"
安卓:layout_toRightOf="@id/kapkanIcon"
安卓:layout_marginLeft="10sp"
安卓:layout_marginTop="15sp"
安卓:layout_gravity="center"
安卓:fontFamily="@font/avenir"
安卓:text="Kapkan"
安卓:textColor="#ffffff"
安卓:textSize="25dp" />
<ImageView
安卓:layout_width="40sp"
安卓:layout_height="40sp"
安卓:layout_alignParentEnd="true"
安卓:layout_marginTop="10sp"
安卓:layout_marginEnd="10dp"
安卓:src="@drawable/ic_arrow_right" />
</RelativeLayout>
<RelativeLayout
安卓:id="@+id/glazButton"
安卓:layout_below="@+id/kapkanButton"
安卓:layout_width="match_parent"
安卓:layout_height="60sp"
安卓:orientation="horizontal">
<ImageView
安卓:id="@+id/glazIcon"
安卓:layout_width="50sp"
安卓:layout_height="50sp"
安卓:layout_marginTop="5sp"
安卓:layout_marginLeft="10sp"
安卓:src="@drawable/ic_glaz"/>
<TextView
安卓:layout_width="wrap_content"
安卓:layout_height="wrap_content"
安卓:layout_toRightOf="@id/glazIcon"
安卓:layout_marginLeft="10sp"
安卓:layout_marginTop="15sp"
安卓:layout_gravity="center"
安卓:fontFamily="@font/avenir"
安卓:text="Glaz"
安卓:textColor="#ffffff"
安卓:textSize="25dp" />
<ImageView
安卓:layout_width="40sp"
安卓:layout_height="40sp"
安卓:layout_alignParentEnd="true"
安卓:layout_marginTop="10sp"
安卓:layout_marginEnd="10dp"
安卓:src="@drawable/ic_arrow_right" />
</RelativeLayout>
<RelativeLayout
安卓:id="@+id/fuzeButton"
安卓:layout_below="@+id/glazButton"
安卓:layout_width="match_parent"
安卓:layout_height="60sp"
安卓:orientation="horizontal">
<ImageView
安卓:id="@+id/fuzeIcon"
安卓:layout_width="50sp"
安卓:layout_height="50sp"
安卓:layout_marginTop="5sp"
安卓:layout_marginLeft="10sp"
安卓:src="@drawable/ic_fuze"/>
<TextView
安卓:layout_width="wrap_content"
安卓:layout_height="wrap_content"
安卓:layout_toRightOf="@id/fuzeIcon"
安卓:layout_marginLeft="10sp"
安卓:layout_marginTop="15sp"
安卓:layout_gravity="center"
安卓:fontFamily="@font/avenir"
安卓:text="Fuze"
安卓:textColor="#ffffff"
安卓:textSize="25dp" />
<ImageView
安卓:layout_width="40sp"
安卓:layout_height="40sp"
安卓:layout_alignParentEnd="true"
安卓:layout_marginTop="10sp"
安卓:layout_marginEnd="10dp"
安卓:src="@drawable/ic_arrow_right" />
</RelativeLayout>
<RelativeLayout
安卓:id="@+id/tachankaButton"
安卓:layout_below="@+id/fuzeButton"
安卓:layout_width="match_parent"
安卓:layout_height="60sp"
安卓:orientation="horizontal">
<ImageView
安卓:id="@+id/tachankaIcon"
安卓:layout_width="50sp"
安卓:layout_height="50sp"
安卓:layout_marginTop="5sp"
安卓:layout_marginLeft="10sp"
安卓:src="@drawable/ic_tachanka"/>
<TextView
安卓:layout_width="wrap_content"
安卓:layout_height="wrap_content"
安卓:layout_toRightOf="@id/tachankaIcon"
安卓:layout_marginLeft="10sp"
安卓:layout_marginTop="15sp"
安卓:layout_gravity="center"
安卓:fontFamily="@font/avenir"
安卓:text="Tachanka"
安卓:textColor="#ffffff"
安卓:textSize="25dp" />
<ImageView
安卓:layout_width="40sp"
安卓:layout_height="40sp"
安卓:layout_alignParentEnd="true"
安卓:layout_marginTop="10sp"
安卓:layout_marginEnd="10dp"
安卓:src="@drawable/ic_arrow_right" />
</RelativeLayout>
</RelativeLayout>
</ScrollView>
</FrameLayout>
# 1 楼答案
当片段被销毁时,尝试删除
ViewTreeObserver.OnScrollChangedListener
,这将避免任何可以附加到已销毁片段上下文的侦听器在您离开并返回该片段时不会被触发第一:为侦听器创建一个全局字段
然后使用创建的字段设置侦听器
然后删除侦听器。。我认为它通常应该在}或{}中尝试
onDestroyView()
>&燃气轮机;但是如果它不起作用,也可以在{这也将解决这个侦听器在片段视图被破坏后触发回调时的内存泄漏问题
更新
它不能处理
onDestroyView()
的原因是OperatorTab
片段是ViewPager
页面的一部分;默认情况下ViewPager
在后台加载许多关闭的页面,以便为下一页滚动做好准备;加载此页面包括一些片段生命周期回调,如onCreateView
、onStart
,但不包括onResume
当您通过将};因此,监听器仍然在那里,在轻击寻呼机几下之后,
ViewPager
滚动到下一个选项卡/页面来离开OperatorTab
^如果ViewPager
决定OperatorTab
是用户稍后可能返回的缓存/关闭页面的一部分,则不会创建{OperatorTab
片段可以从上下文中分离出来,从而使监听器出现内存泄漏因此,在
ViewPager
片段(或任何提前加载其片段的视图)中,最好的方法是在您离开页面时停止任何侦听器,即在onPause
或onStop
回调中,不要等待它们被销毁# 2 楼答案
此错误的一个可能原因是,您在未使用上下文的活动中调用getResources()。因此,您需要使用上下文。getResources()而不是上下文可能是这些here之一。在您的例子中,我认为getContext()可以工作
因此,我认为您应该搜索所有调用getResources的时间,看看是否使用上下文
这个错误的简单解释是,在实例化片段之前,您试图访问getResources()中所需的上下文