片段内部类应该是静态的部类、静态、片段、应该是

2023-09-12 10:56:30 作者:孤独症゛

我有一个 FragmentActivity 类与内部类,应该显示对话框。但我需要使它静态。 Eclipse提供了我晚饭preSS误差 @燮pressLint(ValidFragment)。它是坏的风格,如果我做的,什么是可能的后果?

I have a FragmentActivity class with inner class that should display Dialog. But I am required to make it static. Eclipse offers me to suppress error with @SuppressLint("ValidFragment"). Is it bad style if I do it and what are the possible consequences?

public class CarActivity extends FragmentActivity {
//Code
  @SuppressLint("ValidFragment")
  public class NetworkConnectionError extends DialogFragment {
    private String message;
    private AsyncTask task;
    private String taskMessage;
    @Override
    public void setArguments(Bundle args) {
      super.setArguments(args);
      message = args.getString("message");
    }
    public void setTask(CarActivity.CarInfo task, String msg) {
      this.task = task;
      this.taskMessage = msg;
    }
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
      // Use the Builder class for convenient dialog construction
      AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
      builder.setMessage(message).setPositiveButton("Go back", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int id) {
          Intent i = new Intent(getActivity().getBaseContext(), MainScreen.class);
          startActivity(i);
        }
      });
      builder.setNegativeButton("Retry", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int id) {
          startDownload();
        }
      });
      // Create the AlertDialog object and return it
      return builder.create();
    }
  }

startDownload()启动AsyncTask的。

startDownload() starts Asynctask.

推荐答案

非静态内部类做持有引用其父类。与制作Fragement内部类非静态的问题是,你总是保持一个对活动。该GarbageCollector不能领取活动。这样你就可以泄漏的活动,例如,把方向改变。由于碎片可能仍然活着,并得到插入一个新的活动。

Non static inner classes do hold a reference to their parent classes. The problem with making a Fragement innerclass non-static is that you always hold a reference to the Activity. The GarbageCollector cannot collect your Activity. So you can 'leak' the Activity if for example the orientation changes. Because the Fragment might still live and gets inserted in a new Activity.

编辑:

由于有些人问我要了一些例子,我开始写作之一:

Since some people asked me for some example i started writing one:

虽然这样做,我发现了一些问题比较多使用非静态的片段时:

While doing this i found some more problems when using non static Fragments:

他们不能在一个XML文件中使用,因为他们没有一个空构造(他们可以有一个空的构造,但你平时做实例化非静态内部类

They cannot be used in a xml file since they do not have a empty constructor (They can have an empty constructor, but you usually instantiate nonstatic nested classes by doing

myActivityInstance.new片段() 这是不同的,只要求一个空的构造)

myActivityInstance.new Fragment() and this is different to only calling an empty constructor)

因此​​,为了使我的工作,例如我不得不添加了

So in order to make my example work i had to add the

wrongFragment.setRetainInstance(true);

行不使应用程序崩溃的方向变化。

line to not make the app crash on orientation change.

如果您执行此code,你将有一些textviews和2个按钮的活动 - 按钮增加一些柜台。而Fragements显示,他们认为他们的活动有方向。比赛一开始一切正常。但改变屏幕的方向后,只有第一个片段工作正确地将 - 在其原有的业务,第二个是仍然调用的东西。

if you execute this code you will have an activity with some textviews and 2 buttons - the buttons increase some counter. And the Fragements show the orientation which they think their activity has. At the start everything works correctly. But after changing the screen orientation only the first Fragment works correcly - the second one is still calling stuff at its old activity.

我的活动类:

package com.example.fragmenttest;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class WrongFragmentUsageActivity extends Activity
{
private String mActivityOrientation="";
private int mButtonClicks=0;
private TextView mClickTextView;


private static final String WRONG_FRAGMENT_TAG = "WrongFragment" ;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    int orientation = getResources().getConfiguration().orientation;
    if (orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        mActivityOrientation = "Landscape";
    }
    else if (orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        mActivityOrientation = "Portrait";
    }

    setContentView(R.layout.activity_wrong_fragement_usage);
    mClickTextView = (TextView) findViewById(R.id.clicksText);
    updateClickTextView();
    TextView orientationtextView = (TextView) findViewById(R.id.orientationText);
    orientationtextView.setText("Activity orientation is: " + mActivityOrientation);

    Fragment wrongFragment = (WrongFragment) getFragmentManager().findFragmentByTag(WRONG_FRAGMENT_TAG);
    if (wrongFragment == null)
    {
        wrongFragment = new WrongFragment();
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.add(R.id.mainView, wrongFragment, WRONG_FRAGMENT_TAG);
        ft.commit();
        wrongFragment.setRetainInstance(true); // <-- this is important - otherwise the fragment manager will crash when readding the fragment
    }
}

private void updateClickTextView()
{
    mClickTextView.setText("The buttons have been pressed " + mButtonClicks + " times");
}

private String getActivityOrientationString()
{
    return mActivityOrientation;
}


@SuppressLint("ValidFragment")
public class WrongFragment extends Fragment
{


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        LinearLayout result = new LinearLayout(WrongFragmentUsageActivity.this);
        result.setOrientation(LinearLayout.VERTICAL);
        Button b = new Button(WrongFragmentUsageActivity.this);
        b.setText("WrongFragmentButton");
        result.addView(b);
        b.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                buttonPressed();
            }
        });
        TextView orientationText = new TextView(WrongFragmentUsageActivity.this);
        orientationText.setText("WrongFragment Activities Orientation: " + getActivityOrientationString());
        result.addView(orientationText);
        return result;
    }
}

public static class CorrectFragment extends Fragment
{
    private WrongFragmentUsageActivity mActivity;


    @Override
    public void onAttach(Activity activity)
    {
        if (activity instanceof WrongFragmentUsageActivity)
        {
            mActivity = (WrongFragmentUsageActivity) activity;
        }
        super.onAttach(activity);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        LinearLayout result = new LinearLayout(mActivity);
        result.setOrientation(LinearLayout.VERTICAL);
        Button b = new Button(mActivity);
        b.setText("CorrectFragmentButton");
        result.addView(b);
        b.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mActivity.buttonPressed();
            }
        });
        TextView orientationText = new TextView(mActivity);
        orientationText.setText("CorrectFragment Activities Orientation: " + mActivity.getActivityOrientationString());
        result.addView(orientationText);
        return result;
    }
}

public void buttonPressed()
{
    mButtonClicks++;
    updateClickTextView();
}

}

请注意,你可能不应该投活动onAttach,如果你想用你的片段在不同的活动 - 但这里的工作的例子

note that you should probably not cast the activity in onAttach if you want to use your Fragment in different Activities - but for here its working for the example

在activity_wrong_fragement_usage.xml:

the activity_wrong_fragement_usage.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".WrongFragmentUsageActivity" 
android:id="@+id/mainView">

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

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



<fragment class="com.example.fragmenttest.WrongFragmentUsageActivity$CorrectFragment"
          android:id="@+id/correctfragment"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content" />


</LinearLayout>