본문 바로가기
수업내용

20230721 Android CustomAdapter 2

by titlejjk 2023. 7. 21.

안드로이드 4대 컴포넌트

 

Activity - UI를 제어하는 컨트롤러 하나의 앱의 여러가지가 있을 수 있고 활성화 되어야 사용가능한데 이를 활성화 시키는 것이 intent객체이다. 이 intent는 다른 앱(스마트폰에 기존에 있는 앱 -> 카메라 앱 및 통화 앱)을 활성화 시킬 때 

 

Service - UI가 없는 무언가를 실행할 수 있는 실체를 Service라 칭한다. 안드로이드앱에는 UI는 없지만 실행이 되면 자동으로 어떤 Service가 실행되도록 할수 있다. 예를 들면 위치추적,음악재생 등 BackGround에서 동작하는 부분을 칭한다.

 

BoadcastReceiver -방송수신자를 얘기한다. 스마트폰안에서 일어나는 이벤트들을 수신하는 무언가를 만들 수있다. 예를들면 와이파이,블루투스 의 on,off 배터리의 충전유무 등등을 말한다. 와이파이의 경우 와이파이를 사용 할 수 있고 없고를 특정앱에 알려줘서 사용하게 끔 해주는 기능을 한다.

ContentProvider

오늘은 해당 국기를 눌렀을 때 해당 국가의 정보를 출력해보도록 하겠다.

 

위와 같이 생성해주고 아래와 같은 컨셉으로 만들어 보겠다.

 

 

이렇게만 해준다고 제약조건이 걸리지는 않는다. 그래서 아래와 같이 빨간 줄이 그어진다.

 

 

그래서 제약조건을 걸어주어야 하는데 여러가지 방법이 있지만 이번엔 아래와 같이 제약조건을 걸어주었다.

textview도 만들어주었는데 아래 오른쪽 캡쳐본은 마우스로 설정해줘봤다.

같은 방식으로 버튼도 만들어주었다.

 

어느 정도 틀이 만들어 졌으니

MainActivity에서 DetailActivity로 이동할 메서드를 마저 만들어 준다.

 @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        //DetailActivity로 이동

        //DetailActivity로 이동할 Intent객체 생성하기
        Intent intent =new Intent(this, DetailActivity.class);
        //startActivity()메서드를 호출하면서 Intent객체를 전달해서 액티비티 시작 시키기
        startActivity(intent);
    }

 

위에 코드는 이제 아무거나 눌렀을 때 해당국기만 나오게 되어있는데 이를 좀더 세분화 해보겠다.

 

먼저 알아두어야할 메서드가 있는데 intent객체에 정보를 담을 때 사용되는 메서드는 .putExtra()메서드이다. key, value로 이루어져있다.

거의 웬만하면 담을 수 있긴한데 개발자가 직접 만든 데이터 타입을 담기에는 무리가 있어보인다.

아무리 찾아봐도 Object는 담기 힘들어보이는데 이 때 사용되는 메서드 값은 Serializable(객체 직렬화)을 사용하면된다.

Serializable은 빈 인터페이스이다.

Serializable
public interface Serializable   
Serializability of a class is enabled by the class implementing the java.io.Serializable interface.
Warning: Deserialization of untrusted data is inherently dangerous and should be avoided. Untrusted data should be carefully validated. 
Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.
During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.
When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.
Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:
 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;
 private void readObjectNoData()
     throws ObjectStreamException;
 
The writeObject method is responsible for writing the state of the object for its particular class so that the corresponding readObject method can restore it. The default mechanism for saving the Object's fields can be invoked by calling out.defaultWriteObject. The method does not need to concern itself with the state belonging to its superclasses or subclasses. State is saved by writing the individual fields to the ObjectOutputStream using the writeObject method or by using the methods for primitive data types supported by DataOutput.
The readObject method is responsible for reading from the stream and restoring the classes fields. It may call in.defaultReadObject to invoke the default mechanism for restoring the object's non-static and non-transient fields. The defaultReadObject method uses information in the stream to assign the fields of the object saved in the stream with the correspondingly named fields in the current object. This handles the case when the class has evolved to add new fields. The method does not need to concern itself with the state belonging to its superclasses or subclasses. State is restored by reading data from the ObjectInputStream for the individual fields and making assignments to the appropriate fields of the object. Reading primitive data types is supported by DataInput.
The readObjectNoData method is responsible for initializing the state of the object for its particular class in the event that the serialization stream does not list the given class as a superclass of the object being deserialized. This may occur in cases where the receiving party uses a different version of the deserialized instance's class than the sending party, and the receiver's version extends classes that are not extended by the sender's version. This may also occur if the serialization stream has been tampered; hence, readObjectNoData is useful for initializing deserialized objects properly despite a "hostile" or incomplete source stream.
Serializable classes that need to designate an alternative object to be used when writing an object to the stream should implement this special method with the exact signature:
 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
 
This writeReplace method is invoked by serialization if the method exists and it would be accessible from a method defined within the class of the object being serialized. Thus, the method can have private, protected and package-private access. Subclass access to this method follows java accessibility rules.
Classes that need to designate a replacement when an instance of it is read from the stream should implement this special method with the exact signature.
 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
 
This readResolve method follows the same invocation rules and accessibility rules as writeReplace.
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException . A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
 
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes. Android implementation of serialVersionUID computation will change slightly for some classes if you're targeting android N. In order to preserve compatibility, this change is only enabled is the application target SDK version is set to 24 or higher. It is highly recommended to use an explicit serialVersionUID field to avoid compatibility issues.
Implement Serializable Judiciously
Refer to Effective Java's chapter on serialization for thorough coverage of the serialization API. The book explains how to use this interface without harming your application's maintainability.
Recommended Alternatives
JSON is concise, human-readable and efficient. Android includes both a streaming API  and a tree API  to read and write JSON. Use a binding library like GSON  to read and write Java objects directly.
See also:
ObjectOutputStream 
ObjectInputStream 
ObjectOutput 
ObjectInput 
Externalizable 
           
 
           
Content and code samples on this page are subject to the licenses described in the Content License . Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2022-02-10 UTC.
   
 [{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Missing the information I need" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Too complicated / too many steps" },{ "type": "thumb-down", "id": "outOfDate", "label":"Out of date" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Samples / code issue" },{ "type": "thumb-down", "id": "otherDown", "label":"Other" }]     [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Easy to understand" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Solved my problem" },{ "type": "thumb-up", "id": "otherUp", "label":"Other" }]  
    
 Twitter 
Follow @AndroidDev on Twitter
 YouTube 
Check out Android Developers on YouTube
 LinkedIn 
Connect with the Android Developers community on LinkedIn
    
More Android
Android  
Android for Enterprise  
Security  
Source  
News  
Blog  
Podcasts  
Discover
Gaming  
Machine Learning  
Privacy  
5G  
Android Devices
Large screens  
Wear OS  
ChromeOS devices  
Android for cars  
Android Things  
Android TV  
Releases
Android 13  
Android 12  
Android 11  
Android 10  
Pie  
Oreo  
Nougat  
Documentation and Downloads
Android Studio guide  
Developers guides  
API reference  
Download Studio  
Android NDK  
Support
Report platform bug  
Report documentation bug  
Google Play support  
Join research studies  
   
     
Android  
Chrome  
Firebase  
Google Cloud Platform  
All products  
  
Privacy 
License 
Brand guidelines 
Get news and tips by email Subscribe 
 
English
Bahasa Indonesia
Español – América Latina
Português – Brasil
中文 – 简体
日本語
한국어
  
                              
  < Android API 33, extension level 3 Platform > (android.jar)
`Serializable` on developer.android.com

 

이를 이용해 implements를 해서 CountryDto객체를 Intent객체에 담아 준다. Serializabel로 감싸준다는 느낌?

 

위처럼 해주면 아래와 같은 코드가 가능하다.

 

 @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        //DetailActivity로 이동

        //DetailActivity로 이동할 Intent객체 생성하기
        Intent intent =new Intent(this, DetailActivity.class);
       //클릭한 셀에 있는 나라의 정보.
        Serializable dto=countries.get(i);
        //Intent객체에 "dto"라는 키값으로 Serializable type인 CountryDto객체의 참조값
        intent.putExtra("dto", dto);
        //startActivity()메서드를 호출하면서 Intent객체를 전달해서 Activity시작
        startActivity(intent);
    }

클릭한 셀에 있는 나라의 정보를 Serializable의 타입인 dto에 담아주고 Intent객체의 "dto" key값과 dto값을 .putExtra()메서드를 통해 inten에 담아주고 startAcitivity()메서드에 담아서 객체를 전달해 준다.

 

전달해준 다음 DetailActivity.java에 가서 아래와 같이 코드를 완성 시켜준다.

 

package com.example.step03customadapter;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class DetailActivity extends AppCompatActivity {

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

        //DetailActivity가 활성화 되기 위해서 전달된 Intent객체의 참조값 얻어내기
        Intent intent = getIntent();
        //"dto"라는 키 값으로 담긴 Serializable type의 참조값을 얻어내서 CountryDto type으로 casting
        CountryDto dto = (CountryDto) intent.getSerializableExtra("dto");

        //선택된 cell에 해당하는 CountryDto를 얻어낼 수만 있다면

        //아래의 ImageView와 TextView에 해당 정보를 출력할 수 있다.
        ImageView imageView = findViewById(R.id.imageView);
        imageView.setImageResource(dto.getResId());

        TextView textView = findViewById(R.id.textView);
        textView.setText(dto.getContent());

        //확인 버튼을 눌렀을 때 Activity 종료 시키기
        Button confirmBtn = findViewById(R.id.confirmBtn);
        confirmBtn.setOnClickListener(view -> {
            //finish()메서드를 호출하면 Activity가 종료
            finish();
        });

    }
}

 

DetailActivity가 활성화될 수 있도록 inten객체를 가져오기 위해 getIntent()메서드로 불러오고

.getSerializableExtra로 가져온 "dto"키값을 CountryDto type으로 casting한 후에 dto에 담아준다.

그런다음 imageView.setImageResource()와 textView.setText()메서드를 통해 출력을 해 준다.

 

'수업내용' 카테고리의 다른 글

20230724 Android HttpRequest2  (0) 2023.07.24
20230721 Android HttpRequest  (0) 2023.07.21
20230721 CSS3 Flex  (0) 2023.07.21
20230720 Android CustomAdapter  (0) 2023.07.20
20230720 CSS3 flex2  (0) 2023.07.20

댓글