Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

김영록 3주차 미션 #9

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
52 changes: 52 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import org.jetbrains.kotlin.storage.CacheResetOnProcessCanceled.enabled

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}

android {
namespace = "com.example.carrotmarket"
compileSdk = 33

buildFeatures {
viewBinding = true
}
defaultConfig {
applicationId = "com.example.carrotmarket"
minSdk = 30
targetSdk = 33
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {

implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.carrotmarket

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.myapplication", appContext.packageName)
}
}
32 changes: 32 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<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.MyApplication"
tools:targetApi="31">
<activity
android:name=".AlarmActivity"
android:exported="false" />
<activity
android:name=".StuffInfoActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
23 changes: 23 additions & 0 deletions app/src/main/java/com/example/carrotmarket/ActivityNotify.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.example.carrotmarket

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.carrotmarket.databinding.FragmentActivityNotifyBinding
import com.example.carrotmarket.databinding.FragmentHomeBinding

class ActivityNotify : Fragment() {
lateinit var binding : FragmentActivityNotifyBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentActivityNotifyBinding.inflate(layoutInflater)
return binding.root
}


}
33 changes: 33 additions & 0 deletions app/src/main/java/com/example/carrotmarket/AlarmActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.carrotmarket

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import com.example.carrotmarket.databinding.ActivityAlarmBinding

class AlarmActivity : AppCompatActivity() {
lateinit var binding : ActivityAlarmBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAlarmBinding.inflate(layoutInflater)
setContentView(binding.root)

supportFragmentManager.beginTransaction().replace(R.id.fl_notify_contents, ActivityNotify()).commit()

binding.clActiviyNotify.setOnClickListener {
supportFragmentManager.beginTransaction().replace(R.id.fl_notify_contents, ActivityNotify()).commit()
binding.viewLine1.setBackgroundResource(R.color.black)
binding.viewLine2.setBackgroundResource(R.color.gray)
}

binding.clKeywordNotify.setOnClickListener {
supportFragmentManager.beginTransaction().replace(R.id.fl_notify_contents, KeywordNotify()).commit()
binding.viewLine1.setBackgroundResource(R.color.gray)
binding.viewLine2.setBackgroundResource(R.color.black)
}

binding.btnPrevious.setOnClickListener {
finish()
}
}
}
21 changes: 21 additions & 0 deletions app/src/main/java/com/example/carrotmarket/ChattingFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.carrotmarket

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.carrotmarket.databinding.FragmentChattingBinding

class ChattingFragment : Fragment() {
lateinit var binding : FragmentChattingBinding

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentChattingBinding.inflate(layoutInflater)
return binding.root
}
}
39 changes: 39 additions & 0 deletions app/src/main/java/com/example/carrotmarket/HomeFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.carrotmarket

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.carrotmarket.databinding.FragmentHomeBinding

class HomeFragment : Fragment() {
lateinit var binding: FragmentHomeBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(layoutInflater)

parentFragmentManager.beginTransaction().replace(R.id.fl_stuff_info, HomeScrollFragment()).commit()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScrollView를 프래그먼트로 띄우셨네요!
물론 구현방법에 정답은 존재하지 않지만 몇가지 고려사항을 제시해보겠습니다!

  1. 보통 Fragment를 사용하는 이유는 화면분할 혹은 모듈화 및 재사용성 증가를 위함입니다. 과연 HomeFragment에서 이러한 이점을 얻을 수 있을까요?
  2. Fragment를 사용하려면 FragmentManager를 통해 트랜잭션을 수행해야하는데 이러한 행위가 과도하게 많아질경우 성능오버헤드가 발생할 수 있습니다.
  3. 현재 구조는 액티비티위에 프래그먼트 위에 프래그먼트이며 각각의 단위는 모두 고유한 라이프사이클을 가집니다. 또한 프래그먼트 트랜잭션은 비동기수행되기 때문에 예기치않은 동작을 할 수 도 있습니다. -> 이러한 문제점을 내가 잘 컨트롤할 수 있을지?

물론 프래그먼트는 액티비티보다 가벼운 퍼포먼스를 가지기 때문에 적극 활용하는것은 매우 좋은 선택입니다!
그러나 충분히 하나의 UI내에서 그려낼 수 있는 상황에서 프래그먼트를 추가함으로써 오버헤드를 발생시키게 되는것은 아닌지 고려해보고 설계한다면 더 좋은 사용자경험을 이끌어낼 수 있을것 같습니다!


// 기능 추가
// binding.clItem1.setOnClickListener {
// val intent = Intent(requireContext(), StuffInfoActivity::class.java) // ::은 리플렉션이라고 함 왜 .java붙음?
// startActivity(intent)
// }
// binding.clItem2.setOnClickListener {
// val intent = Intent(requireContext(), StuffInfoActivity::class.java) // ::은 리플렉션이라고 함 왜 .java붙음?
// startActivity(intent)
// }

binding.ivHomeAlarm.setOnClickListener {
val intent = Intent(requireContext(), AlarmActivity::class.java) // ::은 리플렉션이라고 함 왜 .java붙음?
startActivity(intent)
}
Comment on lines +32 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(저도 잘 몰랐던 부분인데 이번기회에 조사해보고 정리한내용 공유드립니닷 ^^7)
리플렉션이란 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API 입니다.
아래 코드를 보실까요

public Intent(Context packageContext, Class<?> cls) {
        throw new RuntimeException("Stub!");
    }

Intent가 실제로 Context와 제네릭 타입의 Class를 인자로 받도록 구현되어 있습니다. 즉 정확히 어떤 클래스를 받을지 명시되지 않았기 때문에 컴파일 시점에서 이를 명시해주어야 하고 리플렉션을 통해 어떤 클래스를 참조하게 할 것인지 명시하고 있는 것입니다.
클래스를 직접 생성해서 인자로 넘겨주는거랑 리플렉션으로 클래스자체를 참조하도록 하는것이랑 무슨차이인지 헷갈릴 수 도 있는데 조금 설명을 덧붙여보겠습니다.
Intent 클래스는 안드로이드 자체적으로 구현되어 있는 Built-in class이고 Intent 클래스 안에서 제네릭 타입의 알 수 없는 어떤 클래스에 대한 모든 Intent 관련 동작이 구현되어 있습니다. 그러나 어떤 클래스가 들어올지는 런타임중에 액션이 일어나는 그 시점에 정해지기 때문에 리플렉션을 통해 참조할 클래스를 알려주는 식으로 구현하고 있는것입니다.
(리플렉션을 사용하면 런타임에 클래스정보를 조사하고 클래스 내의 필드, 메서드 등을 사용할 수 있도록 해줍니다.)
반면에 클래스를 직접 생성하고 해당 인스턴스를 사용하는 것은 정적(컴파일 타임)인 경우에 사용됩니다. 따라서 Built-in Intent 클래스를 사용하지않고 직접 동일한 기능을 구현하여 사용할 수 있다면 직접 객체를 생성하는 방식을 사용해도 무방합니다.

::class로 참조하는 방식은 코틀린의 리플렉션 메서드입니다. 따라서 AClass::class로 참조하게 되면 코틀린의 클래스타입인 KClass 객체가 반환됩니다. 그러나 Intent 코드를 보면 Class를 받도록 되어있기 때문에 자바의 클래스타입인 Class를 반환하도록 AClass::class.java를 사용합니다.

return binding.root
}

}
Loading