Henry Huang's Blog and Documentation
website·Indexed 30 days ago
https://lazy-assedninja.comA collection of development notes and guides by Android Developer Henry Huang. Topics include Android development standards and ADB commands, GCP Nginx reverse proxy setup, Django Line Bot integration, Ktor development notes, and GitHub profile optimization. Also contains deprecated documentation for the WhatToEat project, including API, DB, and requirement specifications.
What's inside Henry Huang
- WhatToEat is a restaurant discovery application designed to solve 'decision paralysis' when choosing where to eat. It allows users to find restaurants based on categories, distance, price, and ratings, while providing businesses with increased exposure and a platform to offer exclusive coupons.
Name string resources in strings.xml
Use underscore naming and the pattern
{module_}logicalNamefor strings to group related strings together.Examples:
main_menu_about: About text in main menufriend_dialog_del: Delete prompt in friend modulebutton_ok: Generic OK button text
WhatToEat deprecated database schema overview
The WhatToEat database (now deprecated) consists of several tables managing users, store information, user interactions (comments, posts, reports), and reservations. Key entities includeUserAccount,Store,Reservation, andSystemLog.Store table schema
TheStoretable contains detailed information about dining establishments, including Google Place IDs, coordinates, and relationships to categories and tags.-- Store Table id: int(pk) place_id: varchar(50) -- Google Place ID name: varchar(50) address: varchar(50) phone: varchar(30) picture: varchar(200) favorite: WhatToEatUserAccount(m2m) -- Users who favorited this store classify: Classify(m2m) -- Categories tag: Tag(fk) -- Tag latitude: varchar(30) longitude: varchar(30) star: float(0) -- Rating website: varchar(300) create_date: datetime modify_date: datetimeWhatToEat application feature overview
WhatToEat is a multi-functional application designed to help users find dining options based on their preferences. Key features include:
- Member Functions: User registration and login to enable posting reviews, saving favorites, and maintaining browsing history.
- Store Listings: Categorized displays of stores (e.g., New Recommendations, Nearby Popular, Monthly Recommendations) including store name, price, description, ratings, and offers.
- Search: Basic search by store name, address, or category.
- Advanced Search: Filtering and exclusion based on category, rating, and distance.
- Review System: Ability to leave text feedback and star ratings for stores.
- Coupons: A centralized view of available store promotions and discounts.
- Favorites: A quick-access list for stores saved by the user.
Android general coding and architecture best practices
Adhere to these architectural and performance guidelines:
- UI/Layout: Use
<merge>,<ViewStub>, and<include>tags to optimize layouts. - Base Classes: Use
BaseActivityandBaseFragmentto handle repetitive operations. - Data Layer: Provide a unified data entry point (e.g., a
DataManagerclass) to encapsulate HTTP, preferences, event posts, and database operations. - Dependency Management: Use
Dagger2for dependency injection to reduce coupling and boilerplate. - Reactive Programming: Use
RxAndroidto simplify logic and event buses (e.g.,EventBus,RxBus) to reduce callbacks between DataLayer and ViewLayer. - Performance:
- Use local variables wherever possible.
- Close Streams immediately after use.
- Avoid repeated calculations in loops (cache the size of the list).
- Use lazy loading (instantiate objects only when needed).
- Avoid
try...catchinside loops; place it at the outermost level. - Use buffered I/O streams.
- Prefer
HashMap,ArrayList, andStringBuilderoverHashTable,Vector, andStringBufferunless thread safety is explicitly required.
// Recommended: Cache list size to avoid repeated calculation for (int i = 0, len = list.size(); i < len; i++) { ... }- UI/Layout: Use
Android method naming conventions
Methods must use lowerCamelCase and typically start with a verb. Common prefixes include:
initXX(): Initialization methodsisXX(),checkXX(): Methods returning a booleangetXX(): Getter methodssetXX(): Setter methodshandleXX(),processXX(): Data processing methodsdisplayXX(),showXX(): Methods that show UI prompts or informationupdateXX(): Data update methodssaveXX(),insertXX(): Data persistence methodsresetXX(): Data reset methodsclearXX(): Data clearing methodsremoveXX(),deleteXX(): Removing data or viewsdrawXX(): Drawing data or effects
Implement a LINE Bot Webhook in Django
To receive events from LINE, you need to implement a webhook endpoint in Django. This requires the
line-bot-sdkpackage and credentials (Channel Access Token and Channel Secret) from the LINE Developers Console.Requirements:
- Install the SDK:
pip install line-bot-sdk - The endpoint must be served over HTTPS. For local development, tools like
ngrokare recommended to provide a public HTTPS URL.
# views.py from django.http import HttpResponse from linebot import LineBotApi, WebhookHandler from linebot.exceptions import LineBotApiError # Initialize SDK line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_LONG_TOKEN') web_hook_handler = WebhookHandler('YOUR_CHANNEL_SECRET') def webhook(request): try: # LINE sends a signature in the headers to verify the request signature = request.headers['X-Line-Signature'] body = request.body.decode() web_hook_handler.handle(body, signature) except LineBotApiError as e: print(str(e)) return HttpResponse("Success.") # LINE requires a successful status code to verify the webhook# urls.py from django.urls import path from . import views urlpatterns = [ path('LineBot/Webhook', views.webhook, name='line_bot_webhook'), ]- Install the SDK:
Implement data serialization with kotlinx.serialization
Ktor supportskotlinx.serialization,Gson, andJackson.kotlinx.serializationis recommended for its wide format support and simplicity. To use it, annotate data classes with@Serializable. Note that you must configure the plugins and dependencies inbuild.gradleand register the JSON converter in the application setup.@Serializable data class Customer(val id: Int, val firstName: String, val lastName: String)Order function parameters in Android
When defining functions in Android development:
- Always place the
Contextas the first parameter. - Always place callback interfaces as the last parameter.
// Context always be first public User loadUser(Context context, int userId); // Callbacks always be last public void loadUserAsync(Context context, int userId, UserCallback callback);- Always place the
Implement Restaurant Interaction and Feedback
Users can interact with restaurant listings through the following features:
- Reviews and Ratings: Members can leave text feedback and star ratings based on their dining experience.
- Favorites: Users can add restaurants to a personal favorites list for quick access.
- Coupons: A dedicated section to view exclusive offers and discounts provided by partner restaurants.
- Community Contributions: Members can add and share their own 'hidden gem' restaurant recommendations publicly.
Organize Android packages by feature (PBF)
It is recommended to use Package By Feature (PBF) instead of Package By Layer (PBL).
Advantages of PBF over PBL:
- High Cohesion/Low Coupling: Related classes (Activity, Fragment, Presenter) for a specific feature are kept together, making them easier to find and modify.
- Private Scope: PBF allows for package-private scope, preventing naming conflicts for utility classes that are only relevant to a specific feature.
- Easier Deletion: Removing a feature is as simple as deleting its corresponding package.
- Better Abstraction: Package names represent functional modules (abstract), while classes inside represent implementation details (concrete).
- Simplified Logic Separation: Logic is separated by classes rather than packages, avoiding redundant package names like
servicecontainingMainService.java.
com └── domain └── app ├── App.java (Application class) ├── Config.java (Constants) ├── base (Base components) ├── custom_view (Custom views) ├── data (Data handling) │ ├── DataManager.java │ ├── local (SP, Database, File) │ ├── model (Data structures, getters/setters) │ └── remote (Remote data) ├── feature (Functional modules) │ └── feature0 │ ├── feature0Activity.java │ ├── feature0Fragment.java │ └── xxAdapter.java ├── injection (Dependency injection) ├── util (Utility classes) └── widget (Component classes)