Data Preparation for the App
In this section, we will outline the data needed for the app and then generate the corresponding Dart model classes. The approach to converting JSON files to Dart models uses the json_model
package mentioned earlier. Before generating the model classes, we will modify some JSON fields, such as adding "?" to indicate that a field is nullable. For more information about json_model
, please refer to its documentation.
1 GitHub Account Information
After logging into GitHub, we need to retrieve the current user's GitHub account information. The GitHub API returns the following JSON structure:
{ "login": "octocat", // User login name "avatar_url": "https://github.com/images/error/octocat_happy.gif", // User avatar URL "type": "User", // User type, could be an organization "name?": "monalisa octocat", // User's name "company?": "GitHub", // Company "blog?": "https://github.com/blog", // Blog URL "location?": "San Francisco", // User's geographical location "email?": "octocat@github.com", // Email "hireable?": false, "bio?": "There once was...", // User bio "public_repos": 2, // Number of public repositories "followers": 20, // Number of followers "following": 0, // Number of accounts being followed "created_at": "2008-01-14T04:33:35Z", // Account creation time "updated_at": "2008-01-14T04:33:35Z", // Account information update time "total_private_repos": 100, // Total number of private repositories (including those in organizations) "owned_private_repos": 100 // Number of the user's own private repositories ... // Other fields omitted}
We will create a file named user.json
in the "jsons" directory to save this information.
2 API Caching Strategy Information
Since accessing GitHub servers can be slow in China, we will implement some simple caching strategies for the GitHub API. We will create a file named cacheConfig.json
in the "jsons" directory to save the caching strategy information, defined as follows:
{ "enable": true, // Whether to enable caching "maxAge": 1000, // Maximum caching duration, in seconds "maxCount": 100 // Maximum number of cached items}
3 User Information
User profiles should include the following information:
GitHub account information; since our app can switch accounts, and it doesn't require logging in again upon reopening, we need to persist user account information and login status.
Application usage configuration; each user should have their own app configuration settings, such as theme, language, and data caching strategies.
After a user logs out, we need to remember the last logged-in username for convenience.
It's important to note that GitHub currently supports three login methods: username/password login, OAuth authorization login, and two-factor authentication login. These methods increase in security. However, for simplicity, we will use username/password login in this example, meaning we need to store the user's password.
Note: It is crucial to emphasize that protecting user account security is a significant and ongoing topic in login scenarios. In actual development, direct storage of user credentials in plaintext should be strictly avoided.
We will create a file named profile.json
in the "jsons" directory with the following structure:
{ "user?": "$user", // GitHub account information, see "user.json" "token?": "", // Login user's token (OAuth) or password "theme": 0, // Theme index "cache?": "$cacheConfig", // Caching strategy information, see "cacheConfig.json" "lastLogin?": "", // Username from the last logout "locale?": "" // App language information}
4 Project Information
Since the app's homepage needs to display all project information, we will create a file named repo.json
in the "jsons" directory to save project details. By referring to the GitHub API documentation for retrieving project information, we define the final structure of repo.json
as follows:
{ "id": 1296269, "name": "Hello-World", // Project name "full_name": "octocat/Hello-World", // Full project name "owner": "$user", // Project owner, see "user.json" "parent?": "$repo", // If it is a forked project, this field contains the parent project information "private": false, // Is it a private project "description": "This your first repo!", // Project description "fork": false, // Is this project a fork "language?": "JavaScript", // Main programming language of the project "forks_count": 9, // Number of times this project has been forked "stargazers_count": 80, // Number of stars for this project "size": 108, // Storage size used by the project "default_branch": "master", // Default branch of the project "open_issues_count": 2, // Current number of open issues for this project "pushed_at": "2011-01-26T19:06:43Z", "created_at": "2011-01-26T19:01:12Z", "updated_at": "2011-01-26T19:14:43Z", "subscribers_count?": 42, // Number of subscribers (followers) for this project "license?": { // Open source license for this project "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZW1pdA==" } ... // Other fields omitted}
5 Generating Dart Model Classes
Now that we have defined the required JSON data, we can run the command provided by the json_model
package to generate the corresponding Dart classes from the JSON files:
flutter packages pub run json_model
After the command executes successfully, you will see the corresponding Dart model classes generated in the lib/models
folder:
├── models │ ├── cacheConfig.dart │ ├── cacheConfig.g.dart │ ├── index.dart │ ├── profile.dart │ ├── profile.g.dart │ ├── repo.dart │ ├── repo.g.dart │ ├── user.dart │ └── user.g.dart
6 Data Persistence
We will use the shared_preferences
package to persist the logged-in user's profile information. shared_preferences
is a Flutter plugin that implements data persistence using mechanisms provided by the Android and iOS platforms. Since using shared_preferences
is very straightforward, readers can refer to its documentation for more details, so we won’t elaborate further here.