Perché il nuovo ADT crea un frammento di classe interna statico per impostazione predefinita?

8

Onestamente, non posso fare a meno di pensare che ciò sia fatto semplicemente per confondere i nuovi arrivati. La maggior parte degli errori su Stack Overflow da parte di nuovi utenti Android deriva principalmente dal fatto che hanno un frammento di classe interna statica che non capiscono come funziona, perché è lì e cercano di utilizzare le attività anche se non comprendono completamente concetto dietro ciò che sta accadendo.

Devo ammettere che ho avuto difficoltà a comprendere l'approccio "PlaceholderFragment", e l'uso di classi interne statiche non è affatto estensibile. La prima cosa che dovresti fare è creare una classe reale al di fuori - ma perché i neofiti devono farlo?

Penso che questo potrebbe essere molto più efficiente se utilizzassero una struttura di progetto simile alla seguente semplice struttura di progetto Android basata su frammenti:

  • src
    • wholepackagename
      • attività
        • MainActivity
      • frammento
        • FirstFragment
        • SecondFragment
  • res
    • Layout
    • Valori
    • ...

Con il codice di

src / wholepackagename / attività / MainActivity:

public class MainActivity extends FragmentActivity implements FirstFragment.Callback
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
        {
            public void onBackStackChanged()
            {
                int backCount = getSupportFragmentManager().getBackStackEntryCount();
                if (backCount == 0)
                {
                    finish();
                }
            }
        });

        if (savedInstanceState == null)
        {
            getSupportFragmentManager().beginTransaction().add(R.id.main_container, new FirstFragment()).addToBackStack(null).commit();
        }
    }

    @Override
    public void firstFragmentCallback()
    {
        getSupportFragmentManager().beginTransaction().replace(R.id.main_container, new SecondFragment()).addToBackStack(null).commit();
    }
} 

src / wholepackagename / frammento / FirstFragment.java:

public class FirstFragment extends Fragment implements View.OnClickListener
{
    private Callback callback;

    private Button firstFragmentButton;

    public static interface Callback
    {
        void firstFragmentCallback();
    }

    public FirstFragment()
    {
        super();
    }

    @Override
    public void onAttach(Activity activity)
    {
        super.onAttach(activity);
        try
        {
            callback = (Callback) activity;
        }
        catch (ClassCastException e)
        {
            Log.e(getClass().getSimpleName(), activity.getClass().getSimpleName() + " must implement Callback interface!", e);
            throw e;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        firstFragmentButton = (Button) rootView.findViewById(R.id.fragment_first_button);
        firstFragmentButton.setOnClickListener(this);
        return rootView;
    }

    @Override
    public void onClick(View v)
    {
        if(v == firstFragmentButton)
        {
            callback.firstFragmentCallback();
        }
    };
}

src / wholepackagename / frammento / SecondFragment.java:

public class SecondFragment extends Fragment implements View.OnClickListener
{
    private Button secondFragmentButton;

    public SecondFragment()
    {
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.fragment_second, container, false);
        secondFragmentButton = (Button) rootView.findViewById(R.id.fragment_second_button);
        secondFragmentButton.setOnClickListener(this);
        return rootView;
    }

    @Override
    public void onClick(View v)
    {
        if(v == secondFragmentButton)
        {
            Toast.makeText(getActivity(), "This is an example!", Toast.LENGTH_LONG).show();
        }
    };
}

Android-Manifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="wholepackagename"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="wholepackagename.activity.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

res / layout / activity_main.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

res / layout / fragment_first.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/fragment_first_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" 
        android:text="@string/first_button" />

</RelativeLayout>

res / layout / fragment_second.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/fragment_second_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/second_button" />

</RelativeLayout>

res / Valori / strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Application name</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="first_button">First Button</string>
    <string name="second_button">Second Button</string>
</resources>


Per me, sembra che il frammento statico della classe interna non supporti realmente alcun tipo di manutenibilità, è difficile vedere cosa sta succedendo e la funzionalità generale non è ovvia in quanto l'attività e il frammento (visualizzazione di frammenti e logica) sono mescolati insieme, che rende difficile vedere e sorvegliare per un principiante.

Credo che fornirebbe un accesso più facile allo sviluppo per la piattaforma Android per avere un esempio come sopra. Ci sono dei benefici per l'approccio attuale, fornendo una classe interiore statica come un frammento?

    
posta Zhuinden 19.07.2014 - 17:36
fonte

1 risposta

1

Io e altri condividiamo il tuo sentimento che I frammenti sono piuttosto strani e non dovrebbe essere accettato ciecamente come Good Things ™.

Ho sempre pensato che l'intenzione dietro la loro esistenza nel codice di bootstrap fosse quella di lanciare Fragments di fronte ai visori degli sviluppatori il prima possibile. Dal momento che i frammenti non sono stati in giro dalla versione 1, immagino che Google abbia sentito il bisogno di mettere un po 'di peso dietro la loro introduzione al fine di ottenere più persone a bordo. Ma, posso solo speculare.

    
risposta data 25.12.2014 - 02:24
fonte

Leggi altre domande sui tag