Fragment(コンストラクタ)

Fragmentのコンストラクタについていろいろ。

Fragment  |  Android Developers
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -
Y.A.M の 雑記帳: Android Fragment で setArguments() してるサンプルが多いのはなぜ?
【Android】Fragmentを使うときのコツとか色々 - Qiita
Fragmentで、パラメータ付きの画面遷移を実装する | mokelab tech sheets
android — フラグメントには本当に空のコンストラクタが必要ですか?

strings.xmlで、

customfragment_textview_textを追加し、CustomFragmentと定義。
customfragment_main.xmlは、

TextViewを置く。
customfragment_textview_textが表示される。
activity_main.xmlは、

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

	<fragment
	    android:id="@+id/customfragment"
	    android:name="com.bgstation0.android.sample.fragment_.CustomFragment"
		android:layout_width="match_parent"
		android:layout_height="match_parent" />
		
</LinearLayout>

XMLでCustomFragment。
MainActivity.javaは、

package com.bgstation0.android.sample.fragment_;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}

最初の状態。
これでCustomFragment.javaを、

package com.bgstation0.android.sample.fragment_;

import android.app.Fragment;

public class CustomFragment extends Fragment {

}

クラス定義だけにしておく。
この状態だと、

落ちる
落ちる

落ちる。
CustomFragmentで何もしていないからね。

package com.bgstation0.android.sample.fragment_;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class CustomFragment extends Fragment {

	// フラグメントのビュー生成時.
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
	
		// ビューの生成.
		return inflater.inflate(R.layout.customfragment_main, null);	// inflateで生成したViewを返す.
		
	}
	
}

onCreateViewのビュー生成があれば、

起動時
起動時

起動時も、

回転時
回転時

回転時も落ちない。
コンストラクタを定義する場合は、publicで引数無しにしないといけない。

package com.bgstation0.android.sample.fragment_;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class CustomFragment extends Fragment {

	// publicな引数なしコンストラクタ.
	public CustomFragment(){
		
	}
	
	// フラグメントのビュー生成時.
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
	
		// ビューの生成.
		return inflater.inflate(R.layout.customfragment_main, null);	// inflateで生成したViewを返す.
		
	}
	
}

もちろん、これは影響なし。

package com.bgstation0.android.sample.fragment_;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class CustomFragment extends Fragment {

	// publicな引数付きコンストラクタ.
	public CustomFragment(String param){
		
	}
	
	// フラグメントのビュー生成時.
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
	
		// ビューの生成.
		return inflater.inflate(R.layout.customfragment_main, null);	// inflateで生成したViewを返す.
		
	}
	
}

引数付きにすると、

落ちる
落ちる

落ちる。
再生成で呼ばれるのは、引数無しのデフォルトコンストラクタだが、引数付きを定義すると、引数無しが存在しなくなるので、例外が発生する。

デフォルトコンストラクタ - コンストラクタ - Java入門

なるほど。Javaのコンストラクタの仕様か。

実は何もしてない
実は何もしてない

実は、Fragmentのコンストラクタは何もしてない。
onCreateViewだけ定義して、コンストラクタを定義していない状態なら、これが呼ばれる。
public引数無しコンストラクタを定義したとしても、何も書かなくてもいい。

package com.bgstation0.android.sample.fragment_;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class CustomFragment extends Fragment {

	// privateな引数なしコンストラクタ.
	private CustomFragment(){
		
	}
	
	// フラグメントのビュー生成時.
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
	
		// ビューの生成.
		return inflater.inflate(R.layout.customfragment_main, null);	// inflateで生成したViewを返す.
		
	}
	
}

privateもダメ。
インナークラスはダメだが、staticインナーはOKみたいな話もあるけど、それについてはちょっと面倒くさそうなので今回はパス。
ここまで、XMLでやってきたが、動的追加の場合もやってみる。

fragmentタグの部分をコメントアウト

再びpublicな引数無しコンストラクタに。

savedInstanceStateがnullなら動的追加。

生成や回転再生成でコンストラクタに来てるか確認
生成や回転再生成でコンストラクタに来てるか確認

生成や回転再生成でコンストラクタに来てるか確認。

起動時の生成ではnullなので追加処理に来てる
起動時の生成ではnullなので追加処理に来てる

MainActivity側では、起動時の生成ではnullなので追加処理に来てる。

回転再生成はnullじゃないので追加処理に来ない
回転再生成はnullじゃないので追加処理に来ない

回転再生成はnullじゃないので追加処理に来ない。
とにかくXMLにしても動的追加にしてもコンストラクタはpublic引数無しにすること。

Sample/android/Fragment/Fragment_0/src/Fragment at master · bg1bgst333/Sample · GitHub