Java Android:片段未附加到活动错误

Java Android:片段未附加到活动错误,java,android,android-fragments,Java,Android,Android Fragments,所以我正在开发一个应用程序,我让这个部分工作了好几天,然后它无缘无故地停止了工作 当我试图在MainActivity中使用另一个headless片段时,我也犯了同样的错误,但最终用MainActivity中的内部方法替换了片段,一切都恢复正常 然而,我不能仅仅为了避免使用片段而重写所有代码。下面是片段代码 public class IMEIFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultC

所以我正在开发一个应用程序,我让这个部分工作了好几天,然后它无缘无故地停止了工作

当我试图在MainActivity中使用另一个headless片段时,我也犯了同样的错误,但最终用MainActivity中的内部方法替换了片段,一切都恢复正常

然而,我不能仅仅为了避免使用片段而重写所有代码。下面是片段代码

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试图制造一个无头碎片。无头碎片= =代码>对象< /代码>。