Henry Huang's Blog and Documentation

website·Indexed 30 days ago

https://lazy-assedninja.com

A 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.

Tokens
19.9K
Snippets
94
Records
140
Agent score
48%

What's inside Henry Huang

  1. WhatToEat Application Overview

    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.
  2. Name string resources in strings.xml

    Use underscore naming and the pattern {module_}logicalName for strings to group related strings together.

    Examples:

    • main_menu_about: About text in main menu
    • friend_dialog_del: Delete prompt in friend module
    • button_ok: Generic OK button text
  3. 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 include UserAccount, Store, Reservation, and SystemLog.
  4. Store table schema

    The Store table 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: datetime
  5. WhatToEat 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.
  6. 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 BaseActivity and BaseFragment to handle repetitive operations.
    • Data Layer: Provide a unified data entry point (e.g., a DataManager class) to encapsulate HTTP, preferences, event posts, and database operations.
    • Dependency Management: Use Dagger2 for dependency injection to reduce coupling and boilerplate.
    • Reactive Programming: Use RxAndroid to 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...catch inside loops; place it at the outermost level.
      • Use buffered I/O streams.
      • Prefer HashMap, ArrayList, and StringBuilder over HashTable, Vector, and StringBuffer unless thread safety is explicitly required.
    // Recommended: Cache list size to avoid repeated calculation
    for (int i = 0, len = list.size(); i < len; i++) {
        ...
    }
  7. Android method naming conventions

    Methods must use lowerCamelCase and typically start with a verb. Common prefixes include:

    • initXX(): Initialization methods
    • isXX(), checkXX(): Methods returning a boolean
    • getXX(): Getter methods
    • setXX(): Setter methods
    • handleXX(), processXX(): Data processing methods
    • displayXX(), showXX(): Methods that show UI prompts or information
    • updateXX(): Data update methods
    • saveXX(), insertXX(): Data persistence methods
    • resetXX(): Data reset methods
    • clearXX(): Data clearing methods
    • removeXX(), deleteXX(): Removing data or views
    • drawXX(): Drawing data or effects
  8. 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-sdk package 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 ngrok are 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'),
    ]
  9. Implement data serialization with kotlinx.serialization

    Ktor supports kotlinx.serialization, Gson, and Jackson. kotlinx.serialization is 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 in build.gradle and register the JSON converter in the application setup.
    @Serializable
    data class Customer(val id: Int, val firstName: String, val lastName: String)
  10. Order function parameters in Android

    When defining functions in Android development:

    • Always place the Context as 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);
  11. 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.
  12. 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 service containing MainService.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)