■ 전반적인 동작구조

Requset -> filter(Character Encoding, CORS관련 제어)-> intercepter(인증,권한 관련) -> JSP(Servlet) ->response


■ Request

* 기본형태

Request-Line

*(( general-header | request-header | entity-header ) CRLF)

CRLF

[ message-body ]


* 예시

Get /test/test.htm HTTP/1.1 //Requset-Line

Accept: */*  //클라이언트가 허용할수 있는 파일형식. */*은 모든 파일형식 지원 의미

Accept-Language: ko //클라이언트가 인식할 수 있는 언어.

Accept-Encoding: gzip, deflate //클라이언트가 인식할 수 있는 인코딩방식.

If-Modified-Since: Fri, 21 Jul 2006 05:31:13 GMT  //페이지가 수정되었을 경우 최신 버전 페이지 요청을 위한 필드

If-None-Match: "734237e186acc61:a1b"

User-Agent: Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1) //브라우저 정보

Host: localhost    //요청한 서버의 HOST

Connection: Keep-Alive


Refer// 특정 페이지에서 링크를 클릭하여 요청할 경우, 링크를 제공한 페이지를 나타낸다.

Cookie : 웹서버가 클라이언트에 쿠키를 저장한 경우, 쿠키의 정보를 이름-값 으로 웹서버에 전송한다.



1. Requset Line

OPTIONS : 요청 URI에서 사용할 수 있는 Method를 물어본다.

GET : 요청 URI의 정보를 가져온다.

HEAD : GET 요청에서 body는 제외하고 헤더만 가져온다.

POST : 요청 URI의 리소스의 새로운 정보를 보낸다.

PUT : 요청 URI에 저장될 정보를 보낸다.

DELETE : 요청 URI의 리소스를 삭제한다.

TRACE : 보낸 메시지를 다시 돌려보낸다.

CONNECT : 프록시에 사용하기 위해 예약된 메서드이다.


*MIME

type/subtype으로 이루어진 방식. 해당 문서가 어떤 타입인지 알려주는 기능을 한다.

ex) text/plain, text/html, multipart/form-data


* 쿠키와 세션

공통점 : 방문자가 브라우저를 열어서 서버에 접속하여 로그인하는 순간.

차이점 : 쿠키(방문자의 정보, 브라우져 종료시 삭제)는 클라이언트에 정보 저장. 세션은 서버에 정보저장. 


2. Request.get

브라우저를 통해 서버에 요청. 이때 request객체에는 요청정보가 담겨있다.

getContextPath(): 컨텍스트패스 ex)localhost 를 얻는다.

getMethod(): 요청이 get방식인지 Post방식인지 구분한다.

getSession(): 세션 객체를 얻는다.

getProtocol(): 프로토콜이 뭔지 알 수 있다. ex)HTTP, SMTP

getRequestURL(): 요청 URL을 얻는다.(http:?/ 부터 시작되는 주소)

getRequestURI() 요청 URI를 얻는다.(상세 주소)

getRemoteAddr(): 서버와 연결된 클라이언트의 IP주소를 구한다.



3. Request Header

- 쿠키 : 웹브라우저의 정보를 웹브라우저에 저장한 후에, 서버에 보내는 요청에 웹브라우저 정보를 포함해서 전송한다. 서버는 요청시 포함된 웹브라우저의 정보를 보고, 동일한 웹브라우저로부터 온 요청인지 판단 가능하다. 사용자의 정보를 유지하는데 사용된다. 유효시간을 통해 생성, 삭제등을 제어한다.

- 캐시 : 사용자가 요청한 정보를 브라우저에 저장하고 나중에는 서버에 요청하지 않고도 브라우저에 저장된 정보 사용가능하여 속도향상. Cache-Control의 옵션을 통해 제어 가능

- 인코딩 : Content-Type의 charset 부분에서 UTF-8 등으로 해당 문서의 문자셋 지정 가능


4. Stateless의 특징

- 주소창에 GET이라는 REST STATE를 나타내는 것을 금지한다.

- ex)biz/plan/produce/order는 허용하지만 biz/plan/produce/getProduceOrder, detailList는 허용하지 않는다.


5. Servlet

- Servlet: 자바를 사용하여 페이지를 동적으로 생성하는 서버 프로그램.


■ Response

- 서버에서 client의 프로그램에게 어떠한 동작을 시킨다.


*기본형태

Status-Line

*(( general-header | response-header | entity-header ) CRLF)

CRLF

[ message-body ]


* 예시

HTTP/1.1 200 OK //HTTP 버전과 응답코드

Server: Microsoft-IIS/5.1   //웹서버의 정보

X-Powered-By: ASP.NET

Date: Fri, 21 Jul 2006 05:32:01 GMT //현재 날짜.

Content-Type: text/html   //요청한 파일의 MIME 타입

Accept-Ranges: bytes

Last-Modified: Fri, 21 Jul 2006 05:31:52 GMT  //요청한 파일의 최종 수정일

ETag: "689cb7f886acc61:a1b"  //캐쉬 업데이트 정보를 위한 임의이 식별 숫자

Content-Length: 101 //헤더 이후 이어지는 파일의 데이터 길이


■ MVC

- Model : Logic

- Conroller : 어떤 로직을 부를지 결정하는 명령어.

- View : Client Side.

- MVC 쓰는 이유 : 유지 ,보수, 변환시 사용이 쉬움. 모델의 변경 없이 컨트롤러, 뷰 만 바꿀 수있고, 재사용 가능. 


■ 필터와 인터셉터

- 필터: 전체 부분에 관한 제어. 문자셋이나 CORS에 관한 부분 

- 인터셉터는 특정 제어를 한다. 인증과 권한에 관련된 부분. 인증은 Session을 체크하여 설정. 권한은 권한체크 따로 있음.

request -> 필터처리 ->인터셉터-> 서버(JSP)<컨트롤러, 서비스, repository) -> Post Interceptor-> filter ->Response


■  MSA란(Micro Service Architecture)

- 하나의 서버에 모든 비즈니스로직이 들어가있는 Monoritic Architecture는 여러 기술 혼용해서 사용하기 어려움. 수정시 컴포넌트간 의존성을 고려해야한다. 

- 따라서 시스템을 독립된 여러개의 시스템으로 나누고, 이 서비스를 조합하는 아키텍쳐 디자인 패턴이 필요.

- MSA는 언어, OS, DB에 관계없이 조합이 가능한 단위의 서비스이다. 서로다른 시스템에서 선택한 기능들만 MSA로 만들고 MSA들을 합치면 새로운 시스템을 구성할 수 있는 구조이다,

- 서비스 : 단일 기능 묶음으로 개발된 서비스 컴포넌트. 데이터 독립적으로 가공, 저장. REST API 통하여 기능 제공


■ Platform>Framework(같은 언어로된 기능의 모임)>Component(기능의 모임)> Library(소규모 기능의 모임)

라이브러리가 바로 msa가 해당되는 부분이다.

Library, Plug In이 담당하는 부분은 기능이다. MSA로 디자인하면 Framework와 관계없이 library, plugin 을 따로 가져다 쓸수 있다.


■ 서비스의 구성

IaaS : AWS. 인프라를 구축하고 조작가능. 서버만 제공하고 나머지는 사용자가 구성

PaaS : Platform. 서비스를 사용자가 설정해서 사용. 플랫폼을 이용하여 응용프로그램을 개발할 수 있는 API까지 제공

SaaS : 클라우드 환경에서 동작하는 어플리케이션을 서비스 형태로 제공하는것. 카페24처럼 가입하고 제공되는 서비스를 사용만 하는 서비스. 


■ Docker : 클릭으로 서비스 구성가능.


■ WAS : 요청에 대하여 처리하고 응답하는 기능을 한다. 


DB관련

■ PreapareStatement와 Statement의 차이

1. Statement는 executeQuery()와 executeUpdate()를 실행하는 시점에 Parameter로 SQL문을 전달한다. 그러나 매번 컴파일 해야한다.

1
2
3
4
5
6
7
8
9
10
11
 <%
    Class.forName("org.h2.Driver");
    String user="sa";
    String password="";
    String url="jdbc:h2:~/test";
    JdbcConnectionPool cp= JdbcConnectionPool.create(url,user,password);
    String sql="SELECT * FROM TEST ORDER BY ID";
    Connection connection=cp.getConnection();
    Statement statement=connection.createStatement();
    ResultSet rs= statement.executeQuery(sql);
%>
cs


2. PreparedStatement는 쿼리문장분석->컴파일-> 실행을 한번만 수행하고 캐시에 담아서 재사용 가능. sql문을 preapareStatement로 컴파일해놓고 ? 부분에만 변화를 주어 계속 재사용이 가능하다. 쿼리에 들어갈 파라미터가 계속 바뀌거나 혹은 바뀌면서 반복해서 수행해야하는 경우 사용한다. 혹은 sql injection공격을 방지하고 싶을때 PreapredStatement를 사용한다.  

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
29
30
31
32
33
34
<%@ page import="java.sql.*" %>
<%
    request.setCharacterEncoding("UTF-8"); //받아오는 값들을 한글로 인코딩합니다.
 
    Class.forName("org.h2.Driver");
    String user="sa";
    String password="";
    String url="jdbc:h2:~/test";
   
    String inputTitle = request.getParameter("title");
    String inputAuthor = request.getParameter("author"); 
    String inputPassword = request.getParameter("password"); 
    String inputContent = request.getParameter("content"); 
    
    try {    
        Connection connection=DriverManager.getConnection(url,user,password);
        
        String sql = "INSERT INTO TEST(TITLE,AUTHOR,PASSWORD,CONTENT,HIT,DATE) VALUES(?,?,?,?,1,sysdate)";
        PreparedStatement pstmt=connection.prepareStatement(sql);
        
        pstmt.setString(1, inputTitle);
        pstmt.setString(2, inputAuthor);
        pstmt.setString(3, inputPassword);
        pstmt.setString(4, inputContent);
        
        pstmt.executeUpdate();
        pstmt.close();
        
        connection.close();
        } catch(SQLException e) {
            out.println( e.toString() );
        } 
 
%>
cs

■ Connection 관련

1. Conn을 종료해주지 않으면 서버에 연결이 상주하기 때문에 close를 해주어야 포트번호 재사용이 가능하다.

2. Connection Pool은 connection에서 session을 따서 쓰는것이다. 미리 연결된 connection에서 Session을 따서 쓸 경우 connection시 필요한 3-handshake과정을 생략해도 되기 때문이다. connection 비용이 크기 때문에 한 내용을 10개로 쪼개어 10번의 connection으로 받는것보다 한 내용을 1번의 connection으로 받고 그 이후에 나누는 것이 좋다. 


* XML은 오류를 허용하지 않지만 HTML은 오류를 어느정도 허용(실행은 가능하도록 만듬)

'Web Programming > HTML,JavaScript' 카테고리의 다른 글

[JavaScript] jQuery 알아두어야할 개념  (0) 2018.09.05
HTML Q&A  (0) 2018.03.18
Javascript Q&A  (0) 2018.03.18

1. DOMContentLoaded Event와 load 이벤트

  jQuery의 ready는 DOMConentLoaded Event의 성격을 갖고있다. DOMConentLoaded Event는 웹페이지 읽고 태그에 해당되는 DOM객체를 생성한 뒤에 실행된다. 이때 문제점은 이미지나 동영상등이 아직 load되지 않을 수 있다는 점이다.  따라서 반드시 이미지나 동영상이 즉시 보여져야되는 상황이라면 window객체의 load 이벤트를 사용해야한다. window.load는 이미지 등의 리소스가 모두 load된다음 발생하는 이벤트이다. 그러나 일반적인 경우에는 $(document).ready()를 더 많이 사용한다.


2. <script>...</script> 부분을 <head>가 아닌 <body>하단에 넣어야하는 이유

  보통의 경우 HTML을 parsing하는 속도가 script를 parsing하는 속도보다 훨씬 빠르다. 이러한 상황에서 script를 head부분에 입력하게 된다면 script를 parsing하는 동안 body부분의 html을 읽지 못해 scirpt를 다 parsing하기 전까지 페이지가 화면에 보이지 않게 되는 경우가 발생한다. 따라서 빨리 parsing이 가능한 html부분이 먼저 parsing되어 화면에 보여지고, 이후에 script부분이 작동될수 있도록 script부분은 body 하단에 입력하는 것이 좋다. 


3. inline tag를 지양해야하는 이유

  코딩을 하다보면 변경사항이 많아진다. 예를 들어 속성에 대한 값을 변경해야할 경우가 생긴다. 이때 인라인태그로 적용했다면 일일이 하나하나 찾아가며 바꾸어야한다. 이러한 비효율성을 방지하기 위해 대부분 class를 사용하여 속성값을 지정하고, 변경사항시 해당 클래스의 내용을 수정하거나, 해당 클래스를 새로운 클래스로 바꾸는 등 한번의 작업으로 모든 사항에 대해 변경이 완료될 수 있도록 해야한다.


4. class의 decoupling이 중요한 이유

  하나의 클래스에 많은 속성값을 부여한다면 coupling이 상승하여 나중에 변경사항이 생길 시 변경사항을 적용하기 어렵다. 

예를들어 어떤 클래스가

.blueCenter {
    background-color: lightblue;
    text-align: center;
}

인 경우, 색상과 정렬 두가지를 동시에 가지고 있다. 이러한 상황에서 정렬은 유지하되 색상만 바꾸려면 클래스명을 모두 바꾸어야한다. 따라서 색상과 정렬을 분리하여

1
2
3
4
5
6
7
.background-blue{
    background-color: lightblue;
}
.text-align-center{
    text-align: center;
}
cs

와 같이 한다면 태그에서 클래스를 background-blue, text-align-center를 적용하고 변경사항이 있을시 둘 중 하나만 변경하거나 제거하면 되서 변경 대응이 유리하다. 이때 클래스명을 명확히하여 이해도를 향상시킬수 있도록 해야한다.

'Web Programming > HTML,JavaScript' 카테고리의 다른 글

[JSP] 대강 알아야할 것들  (0) 2018.09.28
HTML Q&A  (0) 2018.03.18
Javascript Q&A  (0) 2018.03.18

출처 : Bill  Phillips, Android Programming: The Big Nerd Ranch Guide (Big Nerd Ranch Guides) 3st Edition


■ The Need for UI Flexibility

- 리스트를 관리하는 부분 하나, 항목을 관리하는 부분 하나

- 항목을 클릭하는 것은 항목에 관련된 액티비티를 실행

- UI Flexibility: 액티비티의 뷰를 런타임 시점에서 디바이스에 관계없이 재구성하는것

 

■ Introducing Fragments

- Fragment :  Controller Object. 액티비티가 UI 관리를 수행하도록 시킬수 있는 컨트롤러.

- UI Fragment : 각자 자신의 UI를 관리하는 Fragment. Fragment의 View는 UI elements포함 

- Activity의 View에는 다수 Fragment의 View가 삽입될 지점이 있다. 

- Activity는 Fragment로 분할된다.

- 액티비티의 뷰는  Fragment의 View인 FrameLayout으로 정의된다.

- 프래그먼트의 뷰는 Widget들로 구성된다.


■ Two types of fragments 

- Fragment는 어떤 fragment를 implements하느냐에 따라 종류가 나뉜다.

- Native  Fragment : 기기에서 지원하는 Fragment

- Support Fragment : 앱의 라이브러리에서 지원하는 Fragment

- 보통  Support Fragment를 많이 쓴다. 


■ Adding dependencies in Android Studio

- AppCompat 라이브러리를 app/build.gradle에 추가

- build.gradle은 app전체에서 하나, app moudle에 하나 있다.

- dependency추가를 위해서는 app module에서 추가

1
2
3
4
5
6
7
8
9
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0-beta01'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.android.support:recyclerview-v7:28.0.0-beta01'
}
cs

- Dependency 추가한 다음에 Tools-> Android -> Sync Project with gradles files


■ Creating the Crime class

- UUID : 안드로이드 프레임워크에서 사용하는 자바 유틸리티. universally unique ID값 생성.

1
2
3
4
5
6
7
8
9
10
    public class Crime {
        private UUID mId;
        private String mTitle;
        private Date mDate;
        private boolean mSolved;
        public Crime() {
            mId = UUID.randomUUID();
            mDate = new Date();
        }
    }
cs


■ The fragment lifecycle

- 프래그먼트는 액티비티를 대신해 작업하기 때문에 액티비티에 상응하는 프래그먼트의 라이프사이클이 필요하다.

- 프래그먼트 라이프사이클 메소드는 부모 액티비티에 의해 호출된다. 

- 액티비티가 OS에 의해 호출되는것과는 다른 면이다.

- OS는 프래그먼트에 대해 아무런 정보도 알 수 없다. 


■ Two approaches to hosting

- 액티비티에서 UI 프래그먼트를 호스팅하는 방법은 두가지가 있다.

1. 액티비티의 레이아웃에 프래그먼트 추가

2. 액티비티의 코드에서 프래그먼트 추가

- 유연성을 위해서는 코드에서 프래그먼트 추가하는 것이 좋다.


■ Defining a container view 

-  프래그먼트를 사용하기 위한 액티비티의 레이아웃을 FrameLayout가 좋다.

- 프리뷰가 잘 안보이면 Build->Rebuild하거나 앱 껏다켜기


■ Defining CrimeFragment’s layout

- 프래그먼트는 LinearLayout으로 설정


■ Creating the CrimeFragment class

- Fragment는 extends Fragment를 통해 만들어진다.

- android.support.v4.app을 상속한다.


■ Implementing fragment lifecycle methods

- 뷰와 모델을 통해 개별 항목을 표시하고, 유저의 변경사항을 반영하는 역할을 한다.

- Fragment의 onCreate(Bundle)은 public인 반면 Activity의 onCreate(Bundle)은 protected이다.  그 이유는 어떠한 액티비티에서라도 프래그먼트가 호출될 수 있어야하기 때문이다.

- .onSaveInstanceState(Bundle)을 통해 상태를 저장하고 불러올 수 있다.

- onCreate(Bundle)에서는 프래그먼트 인스턴스를 설정할 수 있지만 프래그먼트의 레이아웃은 onCreateVIew에서 해야한다.

1
2
3
4
5
6
7
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_crime, container, false);
        return v;
    }
 
cs

- inflater를 통해 뷰를 불러오고, container는 프래그먼트 뷰의 부모를 의미한다, Bundle은 프래그먼트의 뷰를 부모의 뷰에 inflate할지 여부를 결정한다.

  만약 코드로 자식의 뷰를 부모의 코드에 넣을 것이라면 false를 값으로 둔다.


■ Wiring widgets in a 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
29
public class CrimeFragment extends Fragment {
    private Crime mCrime;
    private EditText mTitleField;
 ...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_crime, container, false);
        mTitleField = (EditText) v.findViewById(R.id.crime_title);
        mTitleField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(
                    CharSequence s, int start, int count, int after) {
// This space intentionally left blank
            }
            @Override
            public void onTextChanged(
                    CharSequence s, int start, int before, int count) {
                mCrime.setTitle(s.toString());
            }
            @Override
            public void afterTextChanged(Editable s) {
// This one too
            }
        });
        return v;
    }
}
 
cs

- findViewById(int)를 통해 뷰를 찾아온다.


■  Adding a UI Fragment to the FragmentManager 

- 프래그먼트를 관리하고 프래그먼트의 레이아웃을 액티비티의 뷰에 넣는 역할을 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class CrimeActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crime);
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);
        if (fragment == null) {
            fragment = new CrimeFragment();
            fm.beginTransaction()
                    .add(R.id.fragment_container, fragment)
                    .commit();
        }
    }
}
 
cs

- 액티비티의 프래그먼트 메니저에서 트랜잭션을 생성하고
- 액티비티의 컨테이너(프래그먼트 리스트) ID와, 새로 생성된 프래그먼트를 매개변수로하여  추가한다는 의미
- 액티비티가 종료될때 프래그먼트 매니저가 리스트를 저장했다가 다시 액티비티가 생성되면 프래그먼트를 프래그먼트 매니저에서 불러온다.
- 만약 해당하는 프래그먼트가 생성된적이 없으면 재생성한다.


■  Application Architecture with Fragments
- 프래그먼트를 남용하는것이 좋지않다. 한 페이지에 프래그먼트가 너무 많으면 어떤 동작을 어떤 프래그먼트가 처리하는지 헷갈리게 된다.
- 따라서 커스텀 뷰를 사용하여 한 페이지에 프래그먼트가 3개 이상 되지 않도록 하는 것이 좋다.
3개 이상이 될 일이 있으면 커스텀 뷰를 사용해 다음 단계로 계층화한다.

'Web Programming > Android' 카테고리의 다른 글

5. Your Second Activity  (0) 2018.08.16
3. The Activity Lifecycle  (0) 2018.08.14
2. Android and Model-ViewController  (0) 2018.08.14
1. Your First Android Application  (0) 2018.08.14

출처 : Bill  Phillips, Android Programming: The Big Nerd Ranch Guide (Big Nerd Ranch Guides) 3st Edition

■ Creating a new activity

- 액티비티를 새로만들때는 Activity, layout, manifest 3개를 건드려야한다.


■ manifest 에서 activities 선언

- 매니페스트는 메타데이터를 안드로이드 OS에 전달하는 파일이다.

1
2
<activity android:name=".CheatActivity">
</activity>
cs

- 위와 같은 형태로 액티비티를 메니페스트 파일에 선언한다.


- Wiring은 다음과 같이 한다 

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 class QuizActivity extends AppCompatActivity {
 ...
 private Button mNextButton;
 private Button mCheatButton;
 private TextView mQuestionTextView;
 ...
 @Override
 protected void onCreate(Bundle savedInstanceState) {
...
mNextButton = (Button) findViewById(R.id.next_button);
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
updateQuestion();
}
});
mCheatButton = (Button)findViewById(R.id.cheat_button);
mCheatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(QuizActivity.this, CheatActivity.class); startActivity(intent);
}
});
updateQuestion();
 }
...
}
cs

■ Activity 시작

- Intent를 통해 한 Activity가 다른 Activity를 실행한다.

- startActivity(Intent)는 OS의 ActivityManager로 보내지고, ActivityManager가 Activity 인스턴스를 만들고 새로 만들어진 인스턴스의 onCreate(Bundle) 메소드를 실행한다. 이때 Intent에 담긴 정보를 바탕으로 ActiivtyManager가 어떤 Activiy를 실행할지 알게된다. 


■ Intent로 정보 주고받기 : ActivityManager에게 무엇을 해야할지 알려주는 용도.

- Intent : Component(Activity) 가 OS와 정보를 주고받기위해 사용하는 객체

- Intent는 전달을 하는 이동 수단이고, Bundle은 저장을 하는 저장 공간이다.

  전달하고자 하는 값을 Bundle에 담아 Intent에 저장하여 전송하는 편이 더 좋다.

1
public Intent(Context packageContext, Class<?> cls)
cs

- Context는 ActivityManager에게  어떤 어플리캐이션 패키지  에서 실행 주체 Activity 클래스를 찾을수 있는지 알려준다.

# Context기본 역할

1) 어플리케이션에 관하여 시스템이 관리하고 있는 정보에 접근하기

  -> getPackageName(), getResource()등의 함수 호출

2) 안드로이드 시스템 서비스에서 제공하는 API 를 호출 할 수 있는 기능 

  -> startActivity(), bindService()등의 함수 호출  

- 매개변수 클래스 부분은 실행 대상 액티비티를 의미한다. 

-  액티비티를 시작하기 전에 ActivityManager는 AndroidMaifest.xml파일을 확인하여 실행하고자하는 액티비티와 같은 이름의 클래스파일이 선언되어있는지 확인한다. 


■ Intent extra로 정보 주고받기 : 다른 엑티비티로 정보 전달(단방향)

-  Intent extra : 실행주체 액티비티에서 Intent에 포함하는 임의의 정보.  인텐트에서의 생성자 매개변수와 같은 의미.

Key,Value 쌍으로 구성되어있다.

1
public Intent putExtra(String name, boolean value)
cs

- OS는 인텐트를 실행대상 액티비티에 전송하고 , EXTRA에 접근해서 데이터를 수신한다.

- EXTRA key 와 Value 추가하기. 그리고 EXTRA_ANSWER_IS_TRUE란 이름으로 answerIsTrue값을 저장. 

1
2
3
4
5
6
7
8
9
10
public class CheatActivity extends AppCompatActivity {
 private static final String EXTRA_ANSWER_IS_TRUE =
"com.bignerdranch.android.geoquiz.answer_is_true";
 public static Intent newIntent(Context packageContext, boolean answerIsTrue) {
Intent intent = new Intent(packageContext, CheatActivity.class);
intent.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);
return intent;
 }
 ...
 

cs

- 실행주체 액티비티에서 정보를 주입하고 인텐트실행하여 실행 대상 액티비티 실행

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 class QuizActivity extends AppCompatActivity {
 ...
 private Button mNextButton;
 private Button mCheatButton;
 private TextView mQuestionTextView;
 ...
 @Override
 protected void onCreate(Bundle savedInstanceState) {
...
mNextButton = (Button) findViewById(R.id.next_button);
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
updateQuestion();
}
});
mCheatButton = (Button)findViewById(R.id.cheat_button);
mCheatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(QuizActivity.this, CheatActivity.class);
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue(); Intent intent = CheatActivity.newIntent(QuizActivity.this, answerIsTrue); startActivity(intent);
}
});
updateQuestion();
 }
...
}
cs

- 실행주체 액티비티에서 보낸 정보를 실행대상 액티비티에서 EXTRA에 담긴 정보를 불러온다.

1
2
public boolean getBooleanExtra(String name, boolean defaultValue)
 
cs


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
29
30
31
32
33
public class CheatActivity extends AppCompatActivity {
 private static final String EXTRA_ANSWER_IS_TRUE =
 "com.bignerdranch.android.geoquiz.answer_is_true";
 private boolean mAnswerIsTrue;
private TextView mAnswerTextView;
 private Button mShowAnswerButton;
 //보내는부분
 public static Intent newIntent(Context packageContext, boolean answerIsTrue) {
Intent intent = new Intent(packageContext, CheatActivity.class);
intent.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);
return intent;
}
//받는부분
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_cheat);
 mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE, false);
mAnswerTextView = (TextView) findViewById(R.id.answer_text_view);
 mShowAnswerButton = (Button) findViewById(R.id.show_answer_button);
 mShowAnswerButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 if (mAnswerIsTrue) {
 mAnswerTextView.setText(R.string.true_button);
 } else {
 mAnswerTextView.setText(R.string.false_button);
 }
 }
 });
 }
 ...
}
 

cs

- getIntent()는 실행대상 activity를 start시킨 인텐트를 불러온다.



자식 엑티비티로 부터 실행결과 전달받기(양방향)

1
2
public void startActivityForResult(Intent intent, int requestCode)
 
cs

1. 부모가 자식에게 값을 보낼때 사용

request code : 유저가 정의한 값. Child activiy에 보내지고 부모로부터 결과를 전송받는 값. 어떤 자식이 부모로 전송했는지 알 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class QuizActivity extends AppCompatActivity {
 private static final String TAG = "QuizActivity";
 private static final String KEY_INDEX = "index";
 private static final int REQUEST_CODE_CHEAT = 0;
 ...
 @Override
 protected void onCreate(Bundle savedInstanceState) {
...
mCheatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Start CheatActivity
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();
Intent intent = CheatActivity.newIntent(QuizActivity.this,
answerIsTrue);
startActivity(intent);
startActivityForResult(intent, REQUEST_CODE_CHEAT);
}
});
cs

2. 자식이 부모로 값을 보냄

1
2
 public final void setResult(int resultCode)
 public final void setResult(int resultCode, Intent data)
cs

result code : Activity.RESULT_OK or Activity.RESULT_CANCELED. result코드에 따라 부모 액티비티에서 할 행동을 정함

setResult intent : 자식에 부모에게 보내는 값

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 class CheatActivity extends AppCompatActivity {
 private static final String EXTRA_ANSWER_IS_TRUE =
 "com.bignerdranch.android.geoquiz.answer_is_true";
 private static final String EXTRA_ANSWER_SHOWN =
 "com.bignerdranch.android.geoquiz.answer_shown";
 ...
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 ...
 mShowAnswerButton.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
if (mAnswerIsTrue) {
 mAnswerTextView.setText(R.string.true_button);
 } else {
 mAnswerTextView.setText(R.string.false_button);
 }
setAnswerShownResult(true);
 }
 });
 }
 private void setAnswerShownResult(boolean isAnswerShown) {
 Intent data = new Intent();
 data.putExtra(EXTRA_ANSWER_SHOWN, isAnswerShown);
 setResult(RESULT_OK, data);
 }
}
 
cs

- 부모에서 EXTRA 리턴할수 있는 함수 작성

1
2
3
4
5
6
7
8
9
public static Intent newIntent(Context packageContext, boolean answerIsTrue) {
 Intent intent = new Intent(packageContext, CheatActivity.class);
 intent.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);
 return intent;
}
public static boolean wasAnswerShown(Intent result) {
 return result.getBooleanExtra(EXTRA_ANSWER_SHOWN, false);
}
 
cs

3. 자식이 부모에게 보낸값 부모에서 처리하기

- 결과값 받는 onActivityResult

1
2
3
4
5
6
7
8
9
10
11
12
   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            return;
        }
        if (requestCode == REQUEST_CODE_CHEAT) {
            if (data == null) {
                return;
            }
            mIsCheater = CheatActivity.wasAnswerShown(data);
        }
    }
cs

 



'Web Programming > Android' 카테고리의 다른 글

7. UI Fragments and the Fragment Manager  (0) 2018.08.20
3. The Activity Lifecycle  (0) 2018.08.14
2. Android and Model-ViewController  (0) 2018.08.14
1. Your First Android Application  (0) 2018.08.14

+ Recent posts