안드로이드에서 Fragment는 거의 필수적으로 사용된다고 볼 수 있다. Activity 위에서 부분 화면을 나타내는데 Fragment는 아주 효율적으로 사용할 수 있다. 그렇다면 Fragment를 어떻게 만들어서 구현을 하는가에 대해서 생각해 볼 필요가 있을 것이다.

  • 일반적으로 나는 Fragment를 사용할 때 아래와 같이 코드를 작성하였다.
1
2
3
4
5
6
7
8
9
public class MyFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState){
View view = inflater.from(viewGroup.context).inflate(R.layout.fragment_my.xml, viewGroup, false);

return view
}
}
  • 위의 코드가 내가 지금까지 Fragment를 사용할 때 작성해왔던 코드이다. 하지만, 최근에 들어서 코드 리뷰를 통해서 이렇게 Fragment를 작성하는게 맞을까란 이야기를 들었다. 보통 관용적으로 newInstance()라는 함수를 사용해서 만들게 되는데 이것과 기본 생성자를 키워드로 찾아보라고 하셨다.

그래서 어떻게?

그래서 어떻게?라니 바로 키워드를 잡고 찾아보기 시작했다. 먼저, newInstance()라는 키워드를 가지고 찾아보니 생성자에 관한 이야기도 함께 설명하는 글을 꽤 찾을 수 있었다.

Fragment를 만들 때는 생성자를 오버로딩 하지 않고 생성 시 필요한 파라미터가 생기면 Bundle 객체에 담아서 setArgument() 함수를 호출하는 방식을 사용하는 것이 일반적이다. 왜냐하면 안드로이드에 의해서 Fragment가 복원될 때는 Fragment의 기본 생성자를 호출하기 때문에 오버로딩된 생성자의 호출이 보장되지 않는다.

그렇기 때문에 아래와 같은 코드를 사용하며 이 코드는 관용적으로 Fragment를 생성할 때 사용하는 코드가 되었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static class DetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();

// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);

return f;
}

public int getShownIndex() {
return getArguments().getInt("index", 0);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
text.setText(String.valueOf(getShownIndex()));
return textView;
}
}
  • 생성자를 만들지 않거나, 기본 생성자를 만들고 아무짓도 하지 않는 것이다. 생성자를 명시하지 않는다면 Java는 자동적으로 기본 생성자를 만든다. 하지만, 기본 생성자를 명시하지 않고 오버로딩된 생성자만 명시하게 되면 Fragment fragment = new Fragment(); 문장을 호출했을 때 에러를 겪게 된다. 그러니 기본 생성자를 사용하도록 하자.(대신 구현은 구현부는 비워놓는다.)
  • 또한, 위에서 설명했던 것처럼 프래그먼트가 복구될 때는 기본 생성자를 호출하기 때문에 오버로딩된 생성자의 호출은 보장되지 않는다. 그래서 저장하거나 넘겨야 할 값이 존재한다면 newInstance() 함수에 파라미터로 전달하고 이 함수 안에서 Bundle 객체를 통해서 파라미터로 넘어온 값을 저장한다.
  • 그리고 복원될 때는 getArguments() 함수를 통해서 값을 복원하면 된다.

참고