모바일 프로그래밍

yhs·2024년 11월 12일

AndroidManifest.xml

  • manifest란 android 빌드 도구, 운영체제및 google play에 앱에 관한 필수 정보를 설명

application

<application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Drugstore">
  • android:allowBackup="true"=>데이터 백업을 할 수 있게 허용
  • android:dataExtractionRules="@xml/data_extraction_rules"
    =>데이터 추출 규칙을 정의하는 XML 파일을 참조
  • android:fullBackupContent="@xml/backup_rules"
    =>백업 규칙을 정의하는 XML 파일을 참조
  • android:icon="@mipmap/ic_launcher"
    =>애플리케이션의 아이콘을 지정
  • android:label="@string/app_name"
    =>애플리케이션의 어플 이름 지정
  • android:roundIcon="@mipmap/ic_launcher_round"
    =>애플리케이션의 원형 아이콘을 지정
  • android:supportsRtl="true"
    =>오른쪽에서 왼쪽(RTL) 레이아웃을 지원하도록 설정
  • android:theme="@style/Theme.Drugstore"
    =>앱에 적용할 기본 테마를 지정

activity(첫번째 화면 설정)

<activity android:name=".First"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  • First는 클래스를 의미하며, android:exported="true">는 다른 애플리케이션이 이 액티비티를 호출할 수 있는지 여부를 결정한다.
  • true로 설정된 경우, 외부 앱이 특정 인텐트를 통해 이 액티비티를 시작할 수 있다.
    =>인텐트? 이러한 어플리케이션 구성요소(컴포넌트) 간에 작업 수행을 위한 정보를 전달하는 역할을 의미
  • 그럼 android:exported="true"> 이걸 안쓰면 어떻게 되는가?
    =>앱이 설치되지 않거나 충돌 발생

activity(나머지 activity들)

 <activity android:name=".MainActivity" android:exported="true" />
        <!-- 다른 액티비티들 -->
        <activity android:name=".DetailActivity" />
        <activity android:name=".DetailActivity1" />
        <activity android:name=".DetailActivity2" />
        <activity android:name=".DetailActivity3" />
        <activity android:name=".DetailActivity4" />
        <activity android:name=".DetailActivity5" />
        <activity android:name=".DetailActivity6" />
  • MainActivity (second_main.xml 사용)
    =>.MainActivity는 이 클래스는 메인 화면 또는 앱의 주요 기능을 제공하는 액티비티로 설정
  • android:exported="true"
    =>이 속성은 외부 애플리케이션이 이 액티비티를 호출할 수 있음을 나타내고, 외부 앱에서 이 액티비티를 실행할 수 있도록 허용
  • 나머지 액티티들
    => exported 속성이 없으므로, 외부에서 접근할 수 없다. 앱 내부에서 호출하도록 설계

First.java

public class First extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 각 버튼 설정
        Button button1 = findViewById(R.id.button);
        Button button2 = findViewById(R.id.button2);
        Button button3 = findViewById(R.id.button3);
        Button button4 = findViewById(R.id.button4);
        Button button5 = findViewById(R.id.button5);
        Button button6 = findViewById(R.id.button6);
        // 버튼 클릭 시 MainActivity로 이동
        View.OnClickListener listener = v -> {
            Intent intent = new Intent(First.this, Second.class);
            startActivity(intent);
        };
        button1.setOnClickListener(listener);
        button2.setOnClickListener(listener);
        button3.setOnClickListener(listener);
        button4.setOnClickListener(listener);
        button5.setOnClickListener(listener);
        button6.setOnClickListener(listener);
    }
}
  • setContentView(R.layout.activity_main)
    =>이 액티비티의 UI 레이아웃을 activity_main.xml로 설정
  • findViewById
    =>레이아웃 파일(activity_main.xml)에 정의된 버튼 요소들을 가져옴
  • View.OnClickListener listener = v->{...}
    =>클릭 리스너를 설정
    =>v->람다 표현식으로 버튼 클릭시 수행할 작업을 정의
    =>람다 표현식? (매개변수) -> { 실행할 코드 }로 익명 함수를 작성할 수 있는 방법이다.
  • Intent intent = new Intent(First.this, Second.class);
    startActivity(intent);
    =>new Intent(First.this, Second.class);는 First 액티비티에서 Second 액티비티로 이동하는 Intent를 생성
    =>startActivity(intent);는 Second 액티비티를 시작
  • 나머지 코드
    =>각 버튼들에 동일한 리스너를 설정

Second.java

public class Second extends AppCompatActivity {
    private RecyclerView recyclerView;
    private ItemAdapter itemAdapter;
    private List<Item> itemList;
    private boolean isDescending = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_main);
        // RecyclerView 초기화 및 GridLayoutManager 설정 (6칸으로 분리)
        recyclerView = findViewById(R.id.recycler_view);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 6,GridLayoutManager.HORIZONTAL,false);
        recyclerView.setLayoutManager(gridLayoutManager);
        // 아이템 데코레이션 추가
        recyclerView.addItemDecoration(new ItemDecoration());
        // 데이터 추가
        itemList = new ArrayList<>();
        for (int i = 1; i <= 6; i++) {  // 예시 데이터 추가
            itemList.add(new Item("제목" + i, i));
        }
        // 어댑터 설정
        itemAdapter = new ItemAdapter(itemList,this);
        recyclerView.setAdapter(itemAdapter);
        // 정렬 버튼 기능
        Button sortButton = findViewById(R.id.sort_button);
        sortButton.setOnClickListener(v -> {
            if (isDescending) {
                Collections.sort(itemList, (a, b) -> Integer.compare(b.getLikeCount(), a.getLikeCount()));
            } else {
                Collections.sort(itemList, (a, b) -> Integer.compare(a.getLikeCount(), b.getLikeCount()));
            }
            isDescending = !isDescending;
            itemAdapter.notifyDataSetChanged();
        });
        // 뒤로가기 버튼 기능
        Button backButton = findViewById(R.id.back_button);
        backButton.setOnClickListener(v -> finish());
    }
    // ItemDecoration 클래스 정의 (아이템 간 간격 조정)
    public class ItemDecoration extends RecyclerView.ItemDecoration {
        private final int spacing = 4; // 간격을 줄여서 아이템이 더 꽉 차게 보이도록 조정
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            outRect.left = spacing;
            outRect.right = spacing;
            outRect.top = spacing;
            outRect.bottom = spacing;
        }
    }
    // ItemClickListener 인터페이스 정의
    public interface ItemClickListener {
        void onItemClick(int position); // 위치 정보를 인자로 받아 어떤 아이템이 클릭되었는지 알 수 있습니다.
    }
    public void onItemClick(int position) {
        Log.d("ItemClick", "Clicked item position: " + position);
        // 여기서 나중에 화면 전환 기능을 추가할 수 있습니다.
    }
}
  • recyclerView: 데이터를 표시할 RecyclerView 객체
  • itemAdapter: RecyclerView의 어댑터로, 데이터를 RecyclerView에 연결
  • itemList: RecyclerView에 표시할 데이터 목록을 담는 리스트
  • isDescending: 데이터가 내림차순인지 여부를 확인하는 변수로, 정렬 순서를 제어
  • setContentView(R.layout.second_main);는 레이아웃 파일(second_main.xml)을 이 액티비티의 UI로 설정

자세히 알아보자

recyclerView = findViewById(R.id.recycler_view);
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 6, GridLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.addItemDecoration(new ItemDecoration());
  • recyclerView를 초기화하고 second_main.xml에 정의된 RecyclerView를 참조
  • GridLayoutManager는 RecyclerView를 그리드 형태로 표시하는 레이아웃 매니저로, 여섯 개의 열로 나눈 수평 레이아웃을 사용
  • RecyclerView의 아이템 간에 간격을 설정하기 위해 ItemDecoration을 추가
itemList = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
    itemList.add(new Item("제목" + i, i));
}
  • itemList를 초기화하고 예시 데이터를 추가
itemAdapter = new ItemAdapter(itemList, this);
recyclerView.setAdapter(itemAdapter);
}
  • itemAdapter를 초기화하고, RecyclerView에 어댑터를 설정하여 itemList에 있는 데이터를 표시
Button sortButton = findViewById(R.id.sort_button);
sortButton.setOnClickListener(v -> {
    if (isDescending) {
        Collections.sort(itemList, (a, b) -> Integer.compare(b.getLikeCount(), a.getLikeCount()));
    } else {
        Collections.sort(itemList, (a, b) -> Integer.compare(a.getLikeCount(), b.getLikeCount()));
    }
    isDescending = !isDescending;
    itemAdapter.notifyDataSetChanged();
});
  • 정렬 버튼(sort_button)을 클릭하면, itemList의 데이터를 likeCount를 기준으로 오름차순 또는 내림차순으로 정렬
  • isDescending 변수의 값을 바꿔가며, 매 클릭마다 정렬 방향을 변경
  • itemAdapter.notifyDataSetChanged();를 호출하여 정렬된 데이터를 RecyclerView에 갱신
Button backButton = findViewById(R.id.back_button);
backButton.setOnClickListener(v -> finish());
  • 뒤로 가기 버튼(back_button)을 클릭하면, 현재 액티비티가 종료되고 이전 화면으로 전환
public class ItemDecoration extends RecyclerView.ItemDecoration {
    private final int spacing = 4;
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.left = spacing;
        outRect.right = spacing;
        outRect.top = spacing;
        outRect.bottom = spacing;
    }
}

ItemAdapter.java

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> 
{
    private final List<Item> itemList;
    private final Context context;
    public ItemAdapter(List<Item> itemList, Context context) {
        this.itemList = itemList;
        this.context = context;
    }
}
  • ItemAdapter 클래스는 RecyclerView.Adapter를 상속하며, 제네릭 타입으로 내부 ViewHolder 클래스를 지정
  • itemList는 Item 객체의 리스트로, RecyclerView에 표시할 데이터
  • context는 현재의 Context를 나타내며, Intent를 생성하여 다른 액티비티로 이동할 때 필요
  • 생성자는 itemList와 context를 초기화
    =>final을 사용함으로써 이 변수들이 어댑터의 전체 수명 동안 불변임을 보장하며, 코드의 안정성과 가독성을 높이는 데 기여
  @NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
    return new ViewHolder(view);
}
  • onCreateViewHolder는 ViewHolder를 생성하는 메서드로, 새로운 아이템 뷰를 생성하고 이를 ViewHolder에 래핑하여 반환
  • LayoutInflater는 item_list.xml 레이아웃을 인플레이트하여 각 항목의 뷰를 생성
  • 이렇게 생성된 ViewHolder는 RecyclerView에 의해 관리되며, onBindViewHolder에서 데이터와 연결
  @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    Item item = itemList.get(position);
    holder.textView.setText(item.getTitle());
    // 각 아이템 클릭 시 DetailActivity로 전환하고 제목을 전달
    holder.itemView.setOnClickListener(v -> {
        Intent intent = new Intent(context, DetailActivity.class);
        intent.putExtra("item_title", item.getTitle());  // 아이템 제목 전달
        context.startActivity(intent);
    });
}
  • onBindViewHolder는 뷰 홀더에 데이터를 설정하는 메서드로써 position 인덱스를 사용하여 itemList에서 데이터를 가져와 뷰에 설정
  • intent.putExtra("item_title", item.getTitle());를 통해 item_title이라는 키로 아이템의 제목을 DetailActivity에 전달
  • context.startActivity(intent);로 DetailActivity를 시작하여 클릭한 아이템의 제목을 새 액티비티에서 사용 가능
  @Override
public int getItemCount() {
    return itemList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
    TextView textView;
    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        textView = itemView.findViewById(R.id.item_text);
    }
}
  • getItemCount는 RecyclerView에 표시할 아이템의 총 개수를 반환.
  • itemList의 크기를 반환하여 아이템 개수를 알려줌
  • ViewHolder 클래스는 각 RecyclerView 항목의 뷰를 담는 래퍼 클래
  • textView는 item_list.xml 레이아웃 파일에 정의된 TextView를 참조하여 각 아이템의 제목을 표시하는 역할
  • 생성자에서는 itemView.findViewById(R.id.item_text);를 통해 TextView를 초기화

RecyclerView와 ItemAdapter의 연결 흐름 요약

  • Second 클래스에서 RecyclerView와 ItemAdapter가 연결된 후, RecyclerView는 각 항목의 뷰가 필요할 때마다 ItemAdapter의 onCreateViewHolder와 onBindViewHolder 메서드를 호출하여 데이터를 표시
  • ItemAdapter는 onCreateViewHolder에서 뷰를 생성하고, onBindViewHolder에서 데이터를 설정하여 RecyclerView에 각 아이템이 표시될 수 있도록 연결하는 역할

ItemAdapter에서 클릭 리스너와 DetailActivity의 흐름및 코드

  public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_detail);
        // Intent로 전달된 아이템 제목 받기
        String itemTitle = getIntent().getStringExtra("item_title");
        // TextView에 제목 표시
        TextView detailText = findViewById(R.id.detail_text);
        if (itemTitle != null) {
            detailText.setText(itemTitle);  // 전달받은 제목 표시
        }
        // 뒤로가기 버튼 설정
        Button backButton = findViewById(R.id.bottom_button);
        backButton.setOnClickListener(v -> finish());
    }
}
  • RecyclerView 항목을 클릭하면 Intent를 통해 DetailActivity가 시작
  • item.getTitle()을 통해 클릭한 아이템의 제목을 Intent에 담아 전달
    -String itemTitle = getIntent().getStringExtra("item_title");는 Intent로 전달된 "item_title"이라는 키를 사용하여 제목을 가져옴
  • itemTitle에는 ItemAdapter에서 클릭한 아이템의 제목이 담김
    -TextView detailText = findViewById(R.id.detail_text);는 second_detail.xml 레이아웃에서 TextView를 가져옴
  • detailText.setText(itemTitle);를 통해 전달받은 itemTitle 값을 TextView에 설정하여 화면에 제목을 표시
  • Button backButton = findViewById(R.id.bottom_button);는 뒤로 가기 버튼을 찾고, backButton.setOnClickListener(v -> finish());를 통해 클릭하면 현재 액티비티를 종료하고 이전 화면으로 돌아가도록 설정
profile
미래의 백엔드

0개의 댓글