IT |
気になる、記になる… |
「Apple Watch Ultra」の裏蓋は開封しないように!! − 素人が元に戻すことは不可能に近い為 |
https://taisy0.com/2022/09/24/162618.html
|
apple |
2022-09-24 00:47:44 |
IT |
気になる、記になる… |
Anker、「Amazon タイムセール祭り」で150製品以上を最大50%オフで販売するセールを開催中 |
https://taisy0.com/2022/09/24/162615.html
|
amazon |
2022-09-24 00:23:11 |
IT |
気になる、記になる… |
「AirPods Pro (第2世代)」では充電ケースの刻印がiPhoneでも表示されるように |
https://taisy0.com/2022/09/24/162609.html
|
airpods |
2022-09-24 00:15:03 |
IT |
気になる、記になる… |
CIO、「Amazon タイムセール祭り」で対象製品を最大40%オフで販売するセールを開催中 |
https://taisy0.com/2022/09/24/162605.html
|
amazon |
2022-09-24 00:00:13 |
IT |
気になる、記になる… |
Spigen、「Amazon タイムセール祭り」で対象製品を最大50%オフで販売するセールを開催中 |
https://taisy0.com/2022/09/24/162602.html
|
amazon |
2022-09-24 00:00:10 |
IT |
気になる、記になる… |
Caseology、「Amazon タイムセール祭り」で「iPhone 14」用ケースを含む対象製品を最大50%オフで販売するセールを開催中 |
https://taisy0.com/2022/09/24/162599.html
|
iphone |
2022-09-24 00:00:09 |
IT |
気になる、記になる… |
Satechi、「Amazon タイムセール祭り」でUSB-Cハブなど3製品を20%オフで販売するセールを開催中 |
https://taisy0.com/2022/09/24/162594.html
|
amazon |
2022-09-24 00:00:07 |
TECH |
Techable(テッカブル) |
安価で使いやすいアシスト機能つきスーツケース登場。スマホ充電機能やTASロックなども搭載 |
https://techable.jp/archives/185769
|
高価 |
2022-09-24 00:00:44 |
python |
Pythonタグが付けられた新着投稿 - Qiita |
OpenAIの音声認識Whisperがすごいので,Google Colabで試してみた(Webアプリを作ってデモ編) |
https://qiita.com/walnut-pro/items/4b57c3cb7a9446f63c21
|
googlecolab |
2022-09-24 09:09:53 |
python |
Pythonタグが付けられた新着投稿 - Qiita |
Python(Django)でSNSアプリケーションの開発Part2~ユーザー認証機能~ |
https://qiita.com/Taku_nakahara/items/e6268ae9ff5b51b042d9
|
django |
2022-09-24 09:03:06 |
Docker |
dockerタグが付けられた新着投稿 - Qiita |
Python(Django)でSNSアプリケーションの開発Part2~ユーザー認証機能~ |
https://qiita.com/Taku_nakahara/items/e6268ae9ff5b51b042d9
|
django |
2022-09-24 09:03:06 |
海外TECH |
DEV Community |
Simple RSS Feed Reader - Jetpack Compose |
https://dev.to/vtsen/simple-rss-feed-reader-jetpack-compose-2ld7
|
Simple RSS Feed Reader Jetpack ComposeHow I build a clean architecture RSS Feed Reader Android app using Kotlin and Jetpack Compose This article was originally published at vtsen hashnode dev on Sep This is my very first Jetpack Compose Android app that I built It is a simple app that reads my blog s rss xml and stores them in a local database You can bookmark articles mark articles as read share articles and search articles by title It shows the full articles content within the app High level ArchitectureThis is the high level architecture design which is based on MVVM recommended Android app architecture As you may already know the UI event flows downward and data flows upward through callback or Flow The dependency direction is also one way from UI layer to Data layer The following table summarizes the responsibility of all the components in UI domain and data layers UI LayerResponsibilityMainActivityConstructs MainViewModel and all its dependencies such as ArticlesRepositoryImpl ArticlesDatabase and WebServiceMainScreenSetup top bar and bottom bar navigation build navigation graph setup snack bar UI displayHomeScreenActs as start destination screen which lists all the articles from rss xml Provides ability to bookmark share mark as unread on each article add search articles feature at top barUnreadScreenLists all unread articles hereBookmarkScreenLists all bookmarked articles hereSearchScreenShows the article search resultsMainViewModelProvides UI states data needed by all the composable functions collect flows from ArticlesRepository refresh the articles in ArticlesRepositoryDomain LayerResponsibilityArticlesRepositoryActs as interface between UI layer and data layer Provides domain data model articles information to the UI layer through FlowData LayerResponsibilityArticlesRepositoryImplImplements the ArticlesRepository interface fetches articles from WebService and write into the ArticlesDatabase map and transform local data to domain dataArticlesDatabaseImplements local RoomDatabase which acts as single source of truthWebServceFetches XML string using ktor client parses the XML feed and converts the XML to remote data which is transformed to local data for local database writing Implementation DetailsI just highlight the high level implementations that worth mentioning The source code shown here may not be complete For details please refer to the source code directly Top and Bottom App BarThe top and bottom app bar are implemented using Scaffold composable function Composablefun MainScreen viewModel MainViewModel useSystemUIController Boolean val scaffoldState rememberScaffoldState val navHostController rememberNavController Scaffold scaffoldState scaffoldState topBar TopBar navHostController viewModel bottomBar BottomBarNav navHostController NavGraph viewModel navHostController Navigation GraphThe navigation graph implementation is very similar to what I did in this article Simple Jetpack Compose Navigation ExampleThe screen navigation back stack looks like this HomeScreen is the start destination which navigates to different screens Because the bottom navigation can navigation from and to any screen calling popUpTo NavRoute Home path us to ensure the back stack is always level depth Composableprivate fun BottomNavigationItem val selected currentNavRoutePath targetNavRoutePath rowScope BottomNavigationItem onClick if selected navHostController navigate targetNavRoutePath popUpTo NavRoute Home path inclusive targetNavRoutePath NavRoute Home path For bottom navigation implementation you can refer to this article How to Add Bottom Navigation in Jetpack Compose Image LoadingFor image loading I used the rememberImagePainter composable function from the coil image loading library Composableprivate fun ArticleImage article Article Image painter rememberImagePainter data article image builder placeholder R drawable loading animation contentScale ContentScale Crop contentDescription modifier Modifier size dp dp clip MaterialTheme shapes medium coil is the only image loading libary that supports Jetpack Compose as far as I knowThere is this landscapist library which wraps around other image loading libraries for Jetpack Compose but I don t know if there are any advantages of using it XML Fetching and ParsingTo fetch the XML remotely I use Ktor Client library which is the multiplatform asynchronous HTTP client The implementation is super simple here class WebService suspend fun getXMlString url String String val client HttpClient val response HttpResponse client request url client close return response body The issue of using Ktor Client is probably its performance Based on my little experience I did on the following article It runs x slower Simple REST API Android App in Kotlin Various HTTP Client Library ImplementationsHowever it is not a direct comparison as this usage pretty straight forward It doesn t use Kotlin Serialization which potentially is the main issue here Well this is something for me to experiment in the future To parse the XML I used the XmlPullParser library FeedPaser parse is the high level implementation It converts the XML string to List lt ArticleFeed gt class FeedParser private val pullParserFactory XmlPullParserFactory newInstance private val parser pullParserFactory newPullParser fun parse xml String List lt ArticleFeed gt parser setInput xml byteInputStream null val articlesFeed mutableListOf lt ArticleFeed gt var feedTitle while parser eventType XmlPullParser END DOCUMENT if parser eventType XmlPullParser START TAG amp amp parser name title feedTitle readText parser else if parser eventType XmlPullParser START TAG amp amp parser name item val feedItem readFeedItem parser val articleFeed ArticleFeed feedItem feedItem feedTitle feedTitle articlesFeed add articleFeed parser next return articlesFeed Local SQLite DatabaseI used the Room database library from Android Jetpack to build the SQLite local database The usage is pretty standard so I m not going to talk about it Instead I share with you what I did a bit differently in the following Instead of hard coding the table name I declare a singleton below object DatabaseConstants const val ARTICLE TABLE NAME article Then I use it in ArticleEntity Entity tableName DatabaseConstants ARTICLE TABLE NAME data class ArticleEntity PrimaryKey autoGenerate true val id Int val title String val link String val author String val pubDate Long val image String val bookmarked Boolean val read Boolean val feedTitle String and also in ArticlesDao interface Daointerface ArticlesDao Query SELECT FROM DatabaseConstants ARTICLE TABLE NAME ORDER by pubDate DESC fun selectAllArticles Flow lt List lt ArticleEntity gt gt Another problem I faced is deleting all the articles does not reset the auto increment of the primary key To fix this I need to bypass Room and run SQL query directly using runSqlQuery to delete the sqlite sequence Database version entities ArticleEntity class exportSchema false abstract class ArticlesDatabase RoomDatabase protected abstract val dao ArticlesDao fun deleteAllArticles dao deleteAllArticles reset auto increment of the primary key runSqlQuery DELETE FROM sqlite sequence WHERE name DatabaseConstants ARTICLE TABLE NAME Article ScreenBy right I should be able to build the article screen from the feed s data but I took the short cut to implement an in app web browser using WebView I just need to wrap it inside the AndroidView composable function Composableprivate fun ArticleWebView url String if url isEmpty return Column AndroidView factory WebView it apply webViewClient WebViewClient loadUrl url It is very simple isn t it The drawback is it doesn t support offline view I did try to work around by loading the HTML instead of URL but no luck Swipe RefreshTo refresh the articles I use the Swipe Refresh library from Accompanist to call MainViewModel refresh when you swipe down the screen Composablefun ArticlesScreen SwipeRefresh state rememberSwipeRefreshState viewModel isRefreshing onRefresh viewModel refresh Data MapperArticle is the domain data used by the UI layer ArticleEntity is the local database data and ArticleFeed is the remote data in data layer The following Kotlin s extension functions are used to implement this data mapping transformation ArticleFeed asArticleEntity ArticleEnitty asArticle Article asArticleEntity To store ArticleFeed into the ArticlesDatabase single source of truth ArticleFeed is required to be converted or mapped to ArticleEntity first To display the Article from ArticlesDatabse ArticleEntity is required to be converted or mapped to Article first To update the ArticlesDatabase e g bookmark the article Article is required to be converted or mapped to the ArticleEntity first This is asArticle extension function as an example which also includes the List lt ArticleEntity gt gt List lt Article gt transformation fun List lt ArticleEntity gt asArticles List lt Article gt return map articleEntity gt articleEntity asArticle fun ArticleEntity asArticle Article return Article id id title title link link author author pubDate pubDate image image bookmarked bookmarked read read feedTitle feedTitle Folder StructureThe high level folder structure looks like this which is organized by layer Since this is a simple app organize by layer makes senses to me For more details about organizing Android package folder structure refer to this article How to Organize Android Package Folder Structure Unit and Instrumented TestsI did not write a lot of testing here The unit test is simply check all articles in MainViewModel are not null For instrumented test I just checked the package name and the bottom navigation names So nothing fancy here but one thing worth mentioning in unit testing is instead of passing useFakeData parameter into the MainViewModel I probably should create FakeArticlesPepositoryImpl instead Beforefun setupViewModel val repository ArticlesRepositoryImpl ArticlesDatabase getInstance ApplicationProvider getApplicationContext WebService viewModel MainViewModel repository mockViewModel MainViewModel repository useFakeData true I should replace ArticlesRepositoryImpl with FakeArticlesRepositoryImpl and get rid of useFakeData true Future WorkOne mistake I made is naming conversion of a composable function that I didn t start with a noun This is quoted from Compose API guidelines Composable annotation using PascalCase and the name MUST be that of a noun not a verb or verb phrase nor a nouned preposition adjective or adverb Nouns MAY be prefixed by descriptive adjectives For example BuildNavGraph should be renamed to NavGraph It is a component widget not an action It shouldn t start with a verb BuildXxx I also tried to convert the MainViewModel to use hilt dependency inject I documented the steps I did in this article Convert View Model to Use Hilt Dependency InjectionSince this my first Jetpack Compose app I m sure there are rooms of improvement All the potential enhancements that can be done for this app is documented in the GitHub s issues here Maybe you can download and install the app and let know any feedbacks Source CodeGitHub Repository Android News See AlsoAndroid Development Tips and Tricks |
2022-09-24 00:17:39 |
ニュース |
BBC News - Home |
Roger Federer: 20-time Grand Slam champion retires after Laver Cup loss |
https://www.bbc.co.uk/sport/tennis/63014093?at_medium=RSS&at_campaign=KARANGA
|
Roger Federer time Grand Slam champion retires after Laver Cup lossRoger Federer brings the curtain down on his illustrious career by teaming up with fellow great Rafael Nadal on an emotional night in London |
2022-09-24 00:44:45 |
ニュース |
BBC News - Home |
Iran protests: US to ease internet curbs for Iranians |
https://www.bbc.co.uk/news/world-middle-east-63013359?at_medium=RSS&at_campaign=KARANGA
|
widespread |
2022-09-24 00:34:40 |
ニュース |
BBC News - Home |
Jhulan Goswami: The highest wicket-taker in women's ODI history to retire |
https://www.bbc.co.uk/news/world-asia-india-62956110?at_medium=RSS&at_campaign=KARANGA
|
international |
2022-09-24 00:10:51 |
ニュース |
BBC News - Home |
Max Whitlock: Olympic champion felt like 'complete failure' after retirement thoughts |
https://www.bbc.co.uk/sport/gymnastics/63005037?at_medium=RSS&at_campaign=KARANGA
|
Max Whitlock Olympic champion felt like x complete failure x after retirement thoughtsThree time Olympic gold medallist Max Whitlock felt like a complete failure when he contemplated stepping away from the sport after the Tokyo Games |
2022-09-24 00:02:35 |
ニュース |
BBC News - Home |
Presidents Cup: Team USA extend lead over International team after day two |
https://www.bbc.co.uk/sport/golf/63016228?at_medium=RSS&at_campaign=KARANGA
|
Presidents Cup Team USA extend lead over International team after day twoThe United States are on course to maintain their Presidents Cup dominance as they extend their lead over the International team to after day two |
2022-09-24 00:34:57 |
ニュース |
BBC News - Home |
Kwarteng's mini-budget: Shock-and-awe tactics from an unapologetic chancellor |
https://www.bbc.co.uk/news/uk-politics-63011639?at_medium=RSS&at_campaign=KARANGA
|
nicholas |
2022-09-24 00:52:08 |
北海道 |
北海道新聞 |
米国、副大統領ら12人国葬へ 岸田首相と26日会談 |
https://www.hokkaido-np.co.jp/article/735535/
|
副大統領 |
2022-09-24 09:27:00 |
北海道 |
北海道新聞 |
【道スポ】日本ハム“神川畑”決勝打 清宮必死のバントに呼応 |
https://www.hokkaido-np.co.jp/article/735534/
|
札幌ドーム |
2022-09-24 09:24:00 |
北海道 |
北海道新聞 |
静岡で住宅に土砂、1人死亡 12万戸停電 |
https://www.hokkaido-np.co.jp/article/735515/
|
土砂崩れ |
2022-09-24 09:18:17 |
北海道 |
北海道新聞 |
<19年間のレガシー 札幌ドームとファイターズ>(2)地元で支える ファン増加 経済回す |
https://www.hokkaido-np.co.jp/article/735532/
|
北海道日本ハム |
2022-09-24 09:19:00 |
北海道 |
北海道新聞 |
NY株4日続落、3万ドル割れ 1年10カ月ぶり安値 |
https://www.hokkaido-np.co.jp/article/735505/
|
続落 |
2022-09-24 09:01:21 |
デザイン |
Webクリエイターボックス |
Twitter 人気のつぶやき 8/20〜9/2 2022 |
https://www.webcreatorbox.com/twitter/twitter-0903-0924-2022
|
firstappearedonweb |
2022-09-24 01:00:16 |
コメント
コメントを投稿