几个月之前,接触Android recovery源代码的时候,看ScreenRecoveryUI类的时候,那时候C++基础还不是特别好,一直不明白以下的初始化方式:
下面这个是Recovery的一个构造函数,代码位于:screen_ui.cpp,它的类的实现在screen_ui.h。
如下这个ScreenRecoveryUI类,这个类是继承于RecoveryUI类的:
这个文件在screen_ui.h
class ScreenRecoveryUI : public RecoveryUI { public: ScreenRecoveryUI(); void Init(); void SetLocale(const char* locale); // overall recovery state ("background image") void SetBackground(Icon icon); // progress indicator void SetProgressType(ProgressType type); void ShowProgress(float portion, float seconds); void SetProgress(float fraction); void SetStage(int current, int max); // text log void ShowText(bool visible); bool IsTextVisible(); bool WasTextEverVisible(); // printing messages void Print(const char* fmt, ...) __printflike(2, 3); void ShowFile(const char* filename); // menu display void StartMenu(const char* const * headers, const char* const * items, int initial_selection); int SelectMenu(int sel); void EndMenu(); void KeyLongPress(int); void Redraw(); enum UIElement { HEADER, MENU, MENU_SEL_BG, MENU_SEL_BG_ACTIVE, MENU_SEL_FG, LOG, TEXT_FILL, INFO }; void SetColor(UIElement e); private: Icon currentIcon; int installingFrame; const char* locale; bool rtl_locale; pthread_mutex_t updateMutex; GRSurface* backgroundIcon[5]; GRSurface* backgroundText[5]; GRSurface** installation; GRSurface* progressBarEmpty; GRSurface* progressBarFill; GRSurface* stageMarkerEmpty; GRSurface* stageMarkerFill; ProgressType progressBarType; float progressScopeStart, progressScopeSize, progress; double progressScopeTime, progressScopeDuration; // true when both graphics pages are the same (except for the progress bar). bool pagesIdentical; size_t text_cols_, text_rows_; // Log text overlay, displayed when a magic key is pressed. char** text_; size_t text_col_, text_row_, text_top_; bool show_text; bool show_text_ever; // has show_text ever been true? char** menu_; const char* const* menu_headers_; bool show_menu; int menu_items, menu_sel; // An alternate text screen, swapped with 'text_' when we're viewing a log file. char** file_viewer_text_; pthread_t progress_thread_; int animation_fps; int installing_frames; int iconX, iconY; int stage, max_stage; void draw_background_locked(Icon icon); void draw_progress_locked(); void draw_screen_locked(); void update_screen_locked(); void update_progress_locked(); static void* ProgressThreadStartRoutine(void* data); void ProgressThreadLoop(); void ShowFile(FILE*); void PutChar(char); void ClearText(); void DrawHorizontalRule(int* y); void DrawTextLine(int* y, const char* line, bool bold); void DrawTextLines(int* y, const char* const* lines); void LoadBitmap(const char* filename, GRSurface** surface); void LoadBitmapArray(const char* filename, int* frames, GRSurface*** surface); void LoadLocalizedBitmap(const char* filename, GRSurface** surface); };
下面是这个类的构造函数的实现,其中构造函数就采用了初始化列表的方式来初始化字段,以下构造函数的实现在screen_ui.cpp文件中可以找到。
ScreenRecoveryUI::ScreenRecoveryUI() : currentIcon(NONE), installingFrame(0), locale(nullptr), rtl_locale(false), progressBarType(EMPTY), progressScopeStart(0), progressScopeSize(0), progress(0), pagesIdentical(false), text_cols_(0), text_rows_(0), text_(nullptr), text_col_(0), text_row_(0), text_top_(0), show_text(false), show_text_ever(false), menu_(nullptr), show_menu(false), menu_items(0), menu_sel(0), file_viewer_text_(nullptr), animation_fps(20), installing_frames(-1), stage(-1), max_stage(-1) { for (int i = 0; i < 5; i++) { backgroundIcon[i] = nullptr; } pthread_mutex_init(&updateMutex, nullptr); }
可以来看看RecoveryUI类:
在ui.h中:
class RecoveryUI { public: RecoveryUI(); virtual ~RecoveryUI() { } // Initialize the object; called before anything else. virtual void Init(); // Show a stage indicator. Call immediately after Init(). virtual void SetStage(int current, int max) = 0; // After calling Init(), you can tell the UI what locale it is operating in. virtual void SetLocale(const char* locale) = 0; // Set the overall recovery state ("background image"). enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR }; virtual void SetBackground(Icon icon) = 0; // --- progress indicator --- enum ProgressType { EMPTY, INDETERMINATE, DETERMINATE }; virtual void SetProgressType(ProgressType determinate) = 0; // Show a progress bar and define the scope of the next operation: // portion - fraction of the progress bar the next operation will use // seconds - expected time interval (progress bar moves at this minimum rate) virtual void ShowProgress(float portion, float seconds) = 0; // Set progress bar position (0.0 - 1.0 within the scope defined // by the last call to ShowProgress). virtual void SetProgress(float fraction) = 0; // --- text log --- virtual void ShowText(bool visible) = 0; virtual bool IsTextVisible() = 0; virtual bool WasTextEverVisible() = 0; // Write a message to the on-screen log (shown if the user has // toggled on the text display). virtual void Print(const char* fmt, ...) __printflike(2, 3) = 0; virtual void ShowFile(const char* filename) = 0; // --- key handling --- // Wait for a key and return it. May return -1 after timeout. virtual int WaitKey(); virtual bool IsKeyPressed(int key); virtual bool IsLongPress(); // Returns true if you have the volume up/down and power trio typical // of phones and tablets, false otherwise. virtual bool HasThreeButtons(); // Erase any queued-up keys. virtual void FlushKeys(); // Called on each key press, even while operations are in progress. // Return value indicates whether an immediate operation should be // triggered (toggling the display, rebooting the device), or if // the key should be enqueued for use by the main thread. enum KeyAction { ENQUEUE, TOGGLE, REBOOT, IGNORE }; virtual KeyAction CheckKey(int key, bool is_long_press); // Called when a key is held down long enough to have been a // long-press (but before the key is released). This means that // if the key is eventually registered (released without any other // keys being pressed in the meantime), CheckKey will be called with // 'is_long_press' true. virtual void KeyLongPress(int key); // Normally in recovery there's a key sequence that triggers // immediate reboot of the device, regardless of what recovery is // doing (with the default CheckKey implementation, it's pressing // the power button 7 times in row). Call this to enable or // disable that feature. It is enabled by default. virtual void SetEnableReboot(bool enabled); // --- menu display --- // Display some header text followed by a menu of items, which appears // at the top of the screen (in place of any scrolling ui_print() // output, if necessary). virtual void StartMenu(const char* const * headers, const char* const * items, int initial_selection) = 0; // Set the menu highlight to the given index, wrapping if necessary. // Returns the actual item selected. virtual int SelectMenu(int sel) = 0; // End menu mode, resetting the text overlay so that ui_print() // statements will be displayed. virtual void EndMenu() = 0; protected: void EnqueueKey(int key_code); private: // Key event input queue pthread_mutex_t key_queue_mutex; pthread_cond_t key_queue_cond; int key_queue[256], key_queue_len; char key_pressed[KEY_MAX + 1]; // under key_queue_mutex int key_last_down; // under key_queue_mutex bool key_long_press; // under key_queue_mutex int key_down_count; // under key_queue_mutex bool enable_reboot; // under key_queue_mutex int rel_sum; int consecutive_power_keys; int last_key; bool has_power_key; bool has_up_key; bool has_down_key; struct key_timer_t { RecoveryUI* ui; int key_code; int count; }; pthread_t input_thread_; void OnKeyDetected(int key_code); static int InputCallback(int fd, uint32_t epevents, void* data); int OnInputEvent(int fd, uint32_t epevents); void ProcessKey(int key_code, int updown); bool IsUsbConnected(); static void* time_key_helper(void* cookie); void time_key(int key_code, int count); };
ui.cpp中,也是采用字段初始化的方式来实现构造函数:
RecoveryUI::RecoveryUI() : key_queue_len(0), key_last_down(-1), key_long_press(false), key_down_count(0), enable_reboot(true), consecutive_power_keys(0), last_key(-1), has_power_key(false), has_up_key(false), has_down_key(false) { pthread_mutex_init(&key_queue_mutex, nullptr); pthread_cond_init(&key_queue_cond, nullptr); memset(key_pressed, 0, sizeof(key_pressed)); }
现在看明白了。
写一个测试案例看看就懂了,果然一例解千愁啊!
#include <iostream> using namespace std ; class ScreenRecoveryUI { private : int r , g , b ; char buffer[10] ; char *p ; public : ScreenRecoveryUI(); void setvalue(int a , int b , int c); void print(); }; //使用初始化列表的方式初始化构造函数里的私有环境变量 ScreenRecoveryUI::ScreenRecoveryUI(): r(0), g(0), b(0), p(nullptr){ for(int i = 0 ; i < 10 ; i++){ buffer[i] = 0 ; } } void ScreenRecoveryUI::setvalue(int a ,int b , int c) { this->r = a ; this->g = b ; this->b = c ; } void ScreenRecoveryUI::print() { cout << "r:" << this->r << endl << "g:" << this->g << endl << "b:" << b << endl ; } int main(void) { ScreenRecoveryUI screen ; screen.setvalue(255,255,0); screen.print(); return 0 ; }
运行结果:
r:255
g:255
b:0