fragmject is a learning project prepared for Kotlin and Jetpack Compose. | fragmject 是一个为初学者准备的上手项目。 通过对 Kotlin 和 Compose 的系统运用,实现的一个功能完备符合主流市场标准 App。 fragmject 没有复杂的业务和多余的封装, 完全依照 Android Developer 官方的写法。 代码简单,内容全面,快速上手,对理解其他项目设计思想和封装技巧也很有帮助。
APACHE-2.0 License
At first glance learning Kotlin was quite difficult, tutorials and videos focused on knowledge points but lacked practical project examples. To overcome this hurdle I created fragmject which provides an example app that demonstrates core features of both Kotlin and Jetpack Compose while keeping things simple enough for beginners to grasp quickly. Special thanks goes out to Wan Android who provide their open API for use with this project!
Fragmject is designed as an easy starting point for those new to programming with Kotlin and Jetpack Compose. By leveraging these technologies we are able to create a fully featured production ready application that adheres strictly to best practices outlined by Google themselves. Fragmject avoids complex business logic or unnecessary layers of abstraction; it simply implements everything according to how you would do so in real life projects following official guidelines provided by Android Developers website. Code is concise yet comprehensive making it straightforward even for someone without any prior experience. It will help you understand design patterns employed elsewhere alongside various techniques used for dependency injection and view binding.
By working through this project you'll gain valuable insights into several areas such as:
In summary, if you're looking for a well structured codebase to learn from then look no further than Fragmject!
In order for you to run this project normally, please use the latest preview version of Android Studio. You can download it at the following address: Download Android Studio | Android Developer
Before diving into this project, here are some basic concepts you might want to familiarize yourself with:
Why does this project avoid depending on external libraries as much as possible? There are two main reasons why relying too heavily on third party libraries can be detrimental to a developer’s growth as a programmer:
Increased Learning Burden: Using libraries that seem simple on the surface can actually involve complex underlying implementations that require deep reading of source code. This can deter developers from exploring additional libraries and learning new skills independently.
Weakened Foundation: New programmers often treat the capabilities offered by thirdparty libraries as part of their own skillset, limiting their ability to work outside of the scope of those libraries. As a result, they losevaluable practice and expertise in general software engineering.
The goal of this project is to encourage students to build a strong foundation in core programming principles by implementing solutions fromscratch wherever possible. Even though the resultingcode maynot alwaysbe elegantor idiomatic,itwillprovide a deeperunderstandingofhowthingsworkandallowsthe studenttobuildmoretransferableskills.
├── app
| └── src
| └── main
| | └── java
| | | ├── bean
| | | ├── components
| | | ├── ui
| | | | └── main
| | | | └── home
| | | | | ├── HomeScreen
| | | | | └── HomeViewModel
| | | | └── MainScreen
| | | ├── utils
| | | ├── WanActivity
| | | ├── WanApplication
| | | ├── WanTheme
| | | ├── WanNavGraph
| | | └── WanViewModel
| | |
| | └── res
| | └── AndroidManifest.xml
| |
| ├── build.gradle
| ├── dictionary
| └── proguard-rules.pro
|
├── library-base
| └── src
| └── main
| | ├── assets
| | └── java
| | ├── activity
| | ├── adapter
| | ├── bus
| | ├── db
| | ├── dialog
| | ├── http
| | ├── provider
| | ├── service
| | ├── utils
| | └── view
| |
| └── build.gradle
|
├── library-picture
|
├── library-plugin
| └── src
| └── main
| ├── kotlin
| └── resources
| └── statistic.properties
|
├── repos
|
├── build.gradle
├── config.properties
├── gradle.properties
└── settings.gradle
Using Compose instead of the traditional Android View system enables us to accomplish more with less code, leading to fewer lines of code needing testing and debugging, and lower likelihood of bugs occurring. This makes maintenance easier for reviewers and maintainers alike, reducing the amount of code that needs to be read, understood, approved, and maintained.
Composereflects a simpler concept in itslayout system,whereallcodeiswritten in one language and located within thesamefile,eliminating theneedfor back-and-forth switching between Kotlin andXML.
User's Question: Compose uses declarative APIs which mean that you only have to define the interface without worrying about how to implement each step.
By leveraging Compose, you can create smaller statelesscomponents that aren't attached to any particular activity or fragment.
In Compose, state is explicit and passed down tocomposable elements allowing them to maintain their integrity while being isolated from other parts of the app. When the statechanges, the UI updates automatically.
Compose is compatible with all your existing code: you can call Compose code from View or call View from Compose. Most commonly used libraries, such as Navigation, ViewModel, and Kotlin coroutine, are suitable for Compose, so you can start adopting them anytime, anywhere.
// send message
SharedFlowBus.with(objectKey: Class<T>).tryEmit(value: T)
// send sticky message
SharedFlowBus.withSticky(objectKey: Class<T>).tryEmit(value: T)
// subscribe message
SharedFlowBus.on(objectKey: Class<T>).observe(owner){ it ->
println(it)
}
// subscribe sticky message
SharedFlowBus.onSticky(objectKey: Class<T>).observe(owner){ it ->
println(it)
}
PictureEditorDialog.newInstance()
.setBitmapPath(path)
.setEditorFinishCallback(object : EditorFinishCallback {
override fun onFinish(path: String) {
val bitmap = BitmapFactory.decodeFile(path, BitmapFactory.Options())
}
})
.show(childFragmentManager)
If you feel that PictureEditorDialog cannot meet the requirements, you can also customize the style through PictureEditorView.
<com.example.miaow.picture.editor.PictureEditorView
android:id="@+id/pic_editor"
android:layout_width="match_parent"
android:layout_height="match_parent" />
picEditor.setBitmapPath(path)
picEditor.setMode(PictureEditorView.Mode.STICKER)
picEditor.setGraffitiColor(Color.parseColor("#ffffff"))
picEditor.setSticker(StickerAttrs(bitmap))
picEditor.graffitiUndo()
picEditor.mosaicUndo()
picEditor.saveBitmap()
That's all for PictureEditorView. For specific usage, please refer to PictureEditorDialogs.
<com.example.miaow.picture.editor.PictureClipView
android:id="@+id/clip"
android:layout_width="match_parent"
android:layout_height="match_parent" />
clip.setBitmapResource(bitmap)
clip.rotate()
clip.reset()
clip.saveBitmap()
That's all for PictureClipView. For specific usage, please refer to PictureClipDialogs.
if (context is AppCompatActivity) {
PictureSelectorDialog.newInstance()
...
.show(context.supportFragmentManager)
}
val calendarState = rememberCalendarState()
calendarState.addSchedule(text)
Calendar(
state = calendarState,
modifier = Modifier.padding(vertical = 15.dp),
onSelectedDateChange = { y, m, d ->
println("CalendarScreen: $y - $m - $d")
}
)
Thank you to all outstanding open source projects^_^
If you like it, I hope to give it to Star or Fork^_^
Thank you~~