아래의 글은 BOOSTER 서포터즈로 활동했던 케니(kart***)님이
작성한 부스트코스 후기입니다.
여러분들의 성원에 더 노력하는 부스트코스가 되겠습니다.
감사합니다.
******************************************
1)링크: https://blog.naver.com/kartmon/221602712096
2)작성날짜: 19/08/02
<본문내용>
1. 화면 전환하기
1) 화면 구성과 화면 간 전환
-액티비티 (화면을 나타내는 것)
-서비스 (화면에 나타나지 않지만 기능이 동작하는 것)
-브로드캐스트 수신자 (sms 문자를 받았을때 내부에서 받을 사람을 처리)
-내용 제공자 (보안 때문에 파일을 그대로 가져가지 못하기 때문에 내용제공자를 통해서 단말에서 파일을 가져올 수 있다)
핵심(인텐트 객체를 통해서 시스템이 처리할 수 있다.)
새로운 액티비티 만들기
-> 새로운 액티비티의 xml 레이아웃 정의하기
-> 메인 액티비티에서 새로운 액티비티 띄우기 (요청코드 전달)
-> 새로운 액티비티에서 응답 보내기 (응답코드)
-> 메인 액티비티에서 응답 처리하기
Manifest 부분
<!--엑티비티의 화면에 대한 기본 설정을 할 수 있다.--><activity android:name=".MenuActivity" android:label="메뉴" android:theme="@style/Theme.AppCompat.DayNight.Dialog"></activity>
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //시스템이 알아볼 수 있는 포멧을 Intent가 가지고 있다. Intent intent = new Intent(getApplicationContext(),MenuActivity.class); //화면을 띄워주고 다시 돌아오기 위함 요청 코드 필요 startActivityForResult(intent,101); } }); } //응답을 받을 메소드 정의 override 사용 -> onActivityResult //data - > intent , requestCode -> 101 , resultCode -> ActivityResultOK가 전달 @Override protected void onActivityResult (int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == 101){ String name = data.getStringExtra("name"); //name에 대한 value값 가져온다 Toast.makeText (getApplicationContext(),"메뉴화면으로부터 응답 : " +name, Toast.LENGTH_LONG).show(); } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_menu); Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); //putExtra - intent 안에 들어가는 데이터 추가(다른 엑티비티로 전달가능) intent.putExtra("name","mike"); //응답에 대한 기본적인 상수를 만든 후 , 응답을 전달 setResult(Activity.RESULT_OK,intent); finish(); //메뉴 화면을 없앤다. -> 메인화면이 보이게 된다. (스택) } }); }
생각해보기
액티비티가 XML 레이아웃 파일과 소스 파일로 구성된다고 했으니 이 각각을 따로 추가할 수도 있을까요?
- 네 레이아웃 파일과 소스파일 각각 추가해서 연결해주면 된다고 생각합니다.
만약 그렇다면 매니페스트에는 어떻게 이 액티비티 정보를 추가해야 할까요?
- 액티비티 항목을 만들어서 정보들을 각각 넣어주면 될것 같습니다.
새로운 액티비티를 띄웠다가 다시 돌아올 때 액티비티 간에 사람 이름이나 나이와 같은 데이터를 전달할 수도 있을까요?
- getExtra에 각각 내용을 추가하여 전달할 수 있다고 생각합니다.
1) 인텐트
화면을 실행 하는 것은 시스템에서 담당한다.
이때 시스템으로 전달하기 위해서는 인텐트라는 객체에 정보를 저장/이용해서 전달을 하게 된다.
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String receiver = editText.getText().toString(); Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + receiver)); startActivity(intent); Intent intent2 = new Intent(); //menuActivity를 가르키는 component name 정보가 만들어지게 된다. //문자열로 컴포넌트를 만들수 있다. ComponentName name = new ComponentName("org.mv.callintent","org.mv.callintent.MenuActivity"); intent2.setComponent(name); } });
생각해보기
여러분이 만드는 앱 말고도 다른 앱들도 인텐트를 사용할 텐데 얼마나 많은 인텐트가 사용되는 걸까요?
- 기본적으로 화면전환시 이외에도 시스템에 접근하는 대부분에 인텐트가 사용되고 있다고 생각합니다.
인텐트의 수가 많다면 그 인텐트들 중에서 특정 인텐트를 구분할 수 있을까요?
- 인텐트의 이름을 선언해서 따로 구분해서 다뤄야 할 것 같습니다.
부가데이터의 크기가 커도 괜찮을까요? 시스템으로 전달되는 데이터이니 크기가 제한될 필요가 있을까요?
- 아무래도 시스템으로 전달되는 데이터 이므로 처리할 수 있는 양의 한계가 생길 것 같습니다. 그래서 제한될 필요가 있다고 생각합니다.
2) 부가데이터
부가 데이터를 Intent를 통해서 전달할때,
//전달 Intent putExtra(String name, String value) Intent putExtra(String name, int value) Intent putExtra(String name, boolean value)//가져올때 String getStringExtra(String name) int getIntExtra(String name, int defaultValue) boolean getBooleanExtra(String name,boolean defaultValue)
Intent에 객체를 통해서 전달 가능하다. (Serializable / Parcelable)
- Serializable을 이용한 intent 전달
(1)mainActivity
@Override public void onClick(View view) { Intent intent = new Intent(getApplicationContext(), MenuActivity.class); ArrayList<String> names = new ArrayList<String>(); names.add("이진호"); names.add("홍진호"); //인텐트에 arrayList 추가 intent.putExtra("names",names); startActivityForResult(intent, 101); } });
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_menu); Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { finish(); //스택 최상위 제거 } }); Intent passedIntent = getIntent(); processIntent(passedIntent); } private void processIntent(Intent intent){ if(intent != null){ //arrayList 를 Serializable을 통해 가져온다. //serializable은 전달되는 데이터량이 크기 때문에 parcelable을 사용하는 것을 권장한다. ArrayList<String> names = (ArrayList<String>)intent.getSerializableExtra("names"); if(names!=null){ Toast.makeText(getApplicationContext(), "전달받은 이름 리스트 갯수 : " + names.size(), Toast.LENGTH_LONG).show(); } } }
- Parcelable을 통해 Intent 전달(Serializable보다 데이터를 경량화 해서 전달 가능) 권장
(1)Parcelable을 implements한 클래스 생성
public class SimpleData implements Parcelable { int number; String message; public SimpleData(int number, String message) { this.number = number; this.message = message; } //parcel에 있는 데이터를 가져온다. public SimpleData(Parcel src){ number = src.readInt(); message = src.readString(); } //creator 필드가 필요함 public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){ //simpleData 객체 생성 public SimpleData createFromParcel(Parcel src){ return new SimpleData(src); } //객체 배열 생성 public SimpleData[] newArray(int size){ return new SimpleData[size]; } }; @Override public int describeContents() { return 0; } //simpleData를 parcel로 바꿔준다. @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(number); parcel.writeString(message); } }
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //일반적으로는 객체를 extra로 전달하지 못하지만 // Parcelable을 통해서 객체를 생성하면 전달가능하다. SimpleData data = new SimpleData(100,"hello"); intent.putExtra("data",data); startActivityForResult(intent, 101); } });
privatevoidprocessIntent(Intent intent){if(intent !=null){//Parcelable을 통해서 데이터 가져오기 SimpleData data =(SimpleData) intent.getParcelableExtra("data");if(data !=null){ Toast.makeText(getApplicationContext(),"전달받은 SimpleData : "+ data.message, Toast.LENGTH_LONG).show();}}}
생각해보기
ArrayList안에 사람 이름을 여러 개 넣은 후 다른 액티비티로 전달하려면 어떻게 해야 할까요?
- putExtra에 arrayList를 넣은 후 전달하면 될 것 같습니다.
사진 이미지와 같이 용량이 큰 파일도 인텐트 안에 부가데이터로 넣을 수 있을까요? 만약에 안된다면 다른 액티비티로 이 사진을 전달할 방법이 있을까요?
- Parcelable로 객체를 만든 후 거기에 이미지의 정보를 저장하여 가져오면 될 것 같습니다.
1) 액티비티 수명주기
실행(Running)
- 액티비티가 보이면서 실행되어 있는 상태 스택의 최상위에 있음
일시 중지(Paused)
- 사용자에게 보여지나 다른 액티비티가 위에 있어서 가려진 상태 (대화상자)
- 중지(Stopped)
- 다른 액티비티에 의해서 완전히 가려져서 보이지 않는 상태
@Override protected void onPause() { super.onPause(); Toast.makeText(this,"onPause() 호출됨",Toast.LENGTH_LONG).show(); //어플이 멈출 때 shared preferences를 이용해 데이터를 저장할 수 있다. SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = pref.edit(); editor.putString("name","소녀시대"); editor.commit(); } @Override protected void onResume() { super.onResume(); Toast.makeText(this,"onResume() 호출됨",Toast.LENGTH_LONG).show(); SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE); //어플이 다시 동작할때 shared preferences를 이용해 데이터를 가져올 수 있다. if(pref != null){ String name = pref.getString("name",""); Toast.makeText(this,"복구된 이름 : "+ name , Toast.LENGTH_LONG).show(); } }
생각해보기
메인 액티비티에서 메뉴 액티비티를 띄운다고 할 때 각각의 액티비티 별로 그 안에 정의한 수명주기 메소드가 호출될까요?
- 네 각각 수명주기 메소드가 호출 될 것 같습니다.
onCreate 외에 자주 호출되는 수명주기 메소드는 어떤 것일까요?
-onStop,onDestroy 를 이용해 데이터를 저장하고 onResume,onStart를 이용해 데이터를 불러오는데 많이 사용 될 것 같습니다.
*********************************************