Java Android:片段未附加到活动错误
所以我正在开发一个应用程序,我让这个部分工作了好几天,然后它无缘无故地停止了工作 当我试图在MainActivity中使用另一个headless片段时,我也犯了同样的错误,但最终用MainActivity中的内部方法替换了片段,一切都恢复正常 然而,我不能仅仅为了避免使用片段而重写所有代码。下面是片段代码Java Android:片段未附加到活动错误,java,android,android-fragments,Java,Android,Android Fragments,所以我正在开发一个应用程序,我让这个部分工作了好几天,然后它无缘无故地停止了工作 当我试图在MainActivity中使用另一个headless片段时,我也犯了同样的错误,但最终用MainActivity中的内部方法替换了片段,一切都恢复正常 然而,我不能仅仅为了避免使用片段而重写所有代码。下面是片段代码 public class IMEIFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultC
public class IMEIFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback{
public static final String TAG_IMEI = "IMEILoader";
protected Activity mActivity;
private String RecordedIMEI;
//public static final String CHECK_INTERNET = "network_connection";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return null; //Do we need this at all?
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
Activity activity = context instanceof Activity ? (Activity) context : null;
mActivity = activity;
}
//Is this needed?
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
activity = getActivity();
if (isAdded() && activity != null) {
super.onAttach(activity);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mActivity = activity;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
public String loadIMEI(Context context) {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// READ_PHONE_STATE permission has not been granted.
requestPermissions(context);
} else {
// READ_PHONE_STATE permission is already been granted.
RecordedIMEI = permissionGrantedActions(context);
}
if (RecordedIMEI != null) {
Log.i("loadIMEIService", "IMEI number returned!");
}
} else {
// READ_PHONE_STATE permission is already been granted.
RecordedIMEI = permissionGrantedActions(context);
}
if (RecordedIMEI != null) {
Log.i("loadIMEIService", "IMEI number returned!");
}
return RecordedIMEI;
}
private void requestPermissions(Context context) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
Log.i("loadIMEIService", "READ_PHONE_STATE permission not granted, asking for it...");
// TODO create proper notification content
PermissionHelper.requestPermissions(((PriceActivity) getActivity()),
new String[]{Manifest.permission.READ_PHONE_STATE},
Constants.PERM_REQUEST_PHONE_STATE,
getString(R.string.notify_perm_title),
getString(R.string.notify_perm_body),
R.drawable.ic_security);
}
}
// Callback received when a permissions request has been completed.
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
boolean isGranted = false;
for (int i = 0; i < grantResults.length; i++)
if (permissions[i].equals(Manifest.permission.READ_PHONE_STATE) && (grantResults[i] == PackageManager.PERMISSION_GRANTED))
isGranted = true;
if (isGranted) {
Context context = getActivity().getApplicationContext();
permissionGrantedActions(context);
}
else
Log.w("loadIMEIService", "READ_PHONE_STATE permission not granted. loadIMEI will not be available.");
}
public String permissionGrantedActions(Context context) {
//Have an object of TelephonyManager
TelephonyManager tm =(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//Get IMEI Number of Phone
String IMEINumber = tm.getDeviceId();
if(IMEINumber != null) {
Log.i("loadIMEIService", "IMEI number recorded!");
}
return IMEINumber;
}
}
以下是我主要活动的相关部分:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDeviceCode = (TextView) findViewById(R.id.device_code);
// Initializing headless fragment
mFragment =
(IMEIFragment) getFragmentManager()
.findFragmentByTag("IMEILoader");
if (mFragment == null) {
mFragment = new IMEIFragment();
getFragmentManager().beginTransaction()
.add(mFragment, "IMEILoader").commit();
}
if (mFragment != null) {
mNumber = mFragment.loadIMEI(MainActivity.this);
mDeviceCode.setText(Html.fromHtml("<b>IMEI</b>: " + mNumber));
}
@覆盖
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDeviceCode=(TextView)findViewById(R.id.device\u代码);
//初始化无头碎片
碎片=
(IMEIFragment)getFragmentManager()
.findFragmentByTag(“IMEILoader”);
if(mFragment==null){
MFFragment=新的IMEIFragment();
getFragmentManager().beginTransaction()
.add(mFragment,“IMEILoader”).commit();
}
if(mFragment!=null){
mNumber=mFragment.loadIMEI(MainActivity.this);
mDeviceCode.setText(Html.fromHtml(“IMEI:+mNumber”);
}
事实上,我已经用了一个多星期的时间使用了完全相同的代码。有人知道问题出在哪里吗
编辑1:错误指向“我的片段”中的requestPermissions。片段应尽可能自包含。您正在从“活动”直接调用IMEIFragment
Caused by: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:805)
at android.app.Fragment.getString(Fragment.java:827)
at com.android.project1.fragments.IMEIFragment.requestPermissions(IMEIFragment.java:107)
at com.android.project1.fragments.IMEIFragment.loadIMEI(IMEIFragment.java:80)
at com.android.project1.main.MainActivity.onCreate(MainActivity.java:108)
您不能这样做。通过活动中的事务添加片段是一个异步操作。例如,当commit()
方法完成时,该片段未初始化。此外,您无法知道它何时初始化。这就是为什么它应该是自包含的。片段决定何时调用loadIMEI(),而不是活动
如果确实需要由活动启动,可以将片段的回调添加到活动中,如下所示:
void onFragmentReady(Fragment f);
或者别的什么
是的,
onCreateView()
应该返回一些内容。如果您的片段真的没有任何UI,您不需要它成为片段。片段应该尽可能自包含。您从活动直接调用IMEIFragment
Caused by: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
at android.app.Fragment.getResources(Fragment.java:805)
at android.app.Fragment.getString(Fragment.java:827)
at com.android.project1.fragments.IMEIFragment.requestPermissions(IMEIFragment.java:107)
at com.android.project1.fragments.IMEIFragment.loadIMEI(IMEIFragment.java:80)
at com.android.project1.main.MainActivity.onCreate(MainActivity.java:108)
您不能这样做。通过活动中的事务添加片段是一个异步操作。例如,当commit()
方法完成时,该片段未初始化。此外,您无法知道它何时初始化。这就是为什么它应该是自包含的。片段决定何时调用loadIMEI(),而不是活动
如果确实需要由活动启动,可以将片段的回调添加到活动中,如下所示:
void onFragmentReady(Fragment f);
或者别的什么
是的,
onCreateView()
应该返回一些内容。如果您的片段实际上根本没有任何UI,您不需要将其作为片段。为什么要对onAttach()进行多个重写?@CSmith如果我没记错的话,它是针对不同的构建版本的,因为某些方法被弃用。我将尝试取出其中一个,看看它是否会影响任何东西。您当然不能从onAttach()调用getActivity(),并期望它能工作。请同时删除onAttach()重写和onDetach(),它们不是必需的。如果您需要访问上下文,请使用getActivity()。请遵循@BlattManw的指导。我们已经介绍了为什么要对onAttach()进行多个重写?@CSmith如果我没记错的话,它是针对不同的构建版本的,因为某些方法被弃用。我将尝试取出其中一个,看看它是否会影响任何东西。您当然不能从onAttach()调用getActivity(),并期望它能工作。请同时删除onAttach()重写和onDetach(),它们是不需要的。如果您需要访问上下文,请使用getActivity()。请遵循@BlattManw的指导。我们已经介绍过,我想我已经了解了您想说的大部分内容。因此,在我的MainActivity中,如果(mFragment!=null){mNumber=mFragment.loadIMEI(MainActivity.this);mDeviceCode.setText(Html.fromHtml(“IMEI:+mNumber”);}>if(mFragment!=null&&mFragment.isAdded()){mNumber=mFragment.loadIMEI(MainActivity.this);mDeviceCode.setText(Html.fromHtml(“IMEI:+mNumber”);}或者我应该在onResume()中调用loadIMEI吗您的活动不应该调用片段类上的任何方法,而应该调用loadIMEI()作为生命周期的一部分。考虑我在RE上面的评论:你真的需要一个片段吗?看起来OP试图制造一个无头碎片。无头碎片= =代码>对象< /代码>。我想我得到了你想要说的大部分。所以,在我的主要活动中,如果(MsActudio!= null){Mult= MFract.LoADeMy,我应该改变这个>。(MainActivity.this);mDeviceCode.setText(Html.fromHtml(“IMEI:+mNumber”);}>if(mFragment!=null&&mFragment.isAdded()){mNumber=mFragment.loadIMEI(MainActivity.this);mDeviceCode.setText(Html.fromHtml(“IMEI:+mNumber”);}或者我应该在onResume()中调用loadIMEI吗你的活动不应该调用你的片段类上的任何方法。你的片段应该调用<代码> LoDyMy()/<代码>作为它的生命周期的一部分。考虑我上面的评论:你真的需要一个片段吗?看起来像OP试图制造一个无头碎片。无头碎片= =代码>对象< /代码>。