Android知識整理

mvc mvp mvvm

mvc是最基礎(chǔ)的架構(gòu),最開始是從web引用過來的,但是在android里面,C就在activity里,activity其實是屬于view層,本身是不能做大量業(yè)務(wù)邏輯處理的,mvc在安卓中就會顯得笨拙,使activity變的繁雜不易維護和拓展,但是小項目又比較合適,正因為大項目使用mvc把activity作用變得不易維護所以衍生出了mvp,mvp是把activity里的業(yè)務(wù)抽出來放到 Presenter里面,把activity的位置還原到view層,去實現(xiàn)用戶的所有操作接口,但是這里又會有個問題,presenter和activity也就是view的交互會很頻繁,而這些操作都是用接口連接的,所以項目會增加很多接口文件,雖然現(xiàn)在有控件可以直接一鍵生成這樣的接口,但是每次增加一個業(yè)務(wù)的時候就會比較繁瑣,會寫很多接口和實現(xiàn)類,但是總的來說用mvp在中大型項目上用的時候可能覺得麻煩一點,但是在單元測試,拓展,維護上會方便很多,而且一個presenter可以用于多個activity,可重用性更高,mvvm是改良版的mvp,它用viewmodel代替了presenter,用dadabinding 做view和viewmode的數(shù)據(jù)綁定,數(shù)據(jù)發(fā)生改變view就會跟著改變,因為livedata 生命周期通過lifecycle和activity綁定,所以一定程度上app了頁面的內(nèi)存泄露問題,mvvm是現(xiàn)在主流的架構(gòu)也是Google主推的架構(gòu)

多線程

http網(wǎng)絡(luò)請求多線程,照片上傳多線程,人像比對多線程 多線程主要是要處理線程之間的共享變量,比如幾個線程同時請求,而請求結(jié)果需要做一個回調(diào),每個線程請求成功需要做一個計數(shù)器,而這個計數(shù)器就是共享變量,多線程操作共享變量需要加鎖synconizied,并且用volatile修飾保證變量操作的唯一性

join:調(diào)用join就是調(diào)用當(dāng)前線程的wait方法,等待join線程執(zhí)行完畢在調(diào)用當(dāng)前線程的notify方法恢復(fù)執(zhí)行,join方法必須要在線程運行之后才有效

如何保證你的線程執(zhí)行完

對于需要鎖屏后繼續(xù)執(zhí)行的任務(wù),優(yōu)先使用 WorkManager或前臺服務(wù),而不是依賴 Activity 生命周期內(nèi)的普通線程。

kotlin

很多只是寫法變了,關(guān)鍵字變了,邏輯還是差不多的,比如switch變成了when,for循環(huán)變成for in,還有就是一些權(quán)限修飾符變了,默認(rèn)權(quán)限是final,open標(biāo)識可繼承,可重寫,增加了新的權(quán)限internal標(biāo)識在當(dāng)前module中使用用起來比java方便,省掉了很多代碼,比如那種非空判斷只需要語句中加個問號就行,邏輯都是差不多的

kotlin沒有static的變量,只能用companion派生對象關(guān)鍵字修飾,全局靜態(tài)對象用Object關(guān)鍵字(Util工具類)const常量

高階函數(shù)

    forEach     遍歷數(shù)組

    map    數(shù)組轉(zhuǎn)換

    flatmap    多維數(shù)組轉(zhuǎn)換

    let     變量定義作用域,非空判斷 返回最后一行

    with    傳入對象,作用域最后一行是返回值

    run    只接受lambda函數(shù) 返回最后一行

    apply,返回函數(shù)本身作用域,減少重復(fù)引用 不改變值 

tcp/ip http

這些協(xié)議原理還是很深的,首先他們的層級是不一樣的,ip協(xié)議是用于網(wǎng)絡(luò)層的,tcp是傳輸層,http是應(yīng)用層,然后tcp又涉及到三次握手,對于這些協(xié)議我沒有研究的很深,平常用的多的還是http協(xié)議,http協(xié)議是建立在tcp上的一種應(yīng)用,他的特點就是每次發(fā)出請求都需要服務(wù)端回送響應(yīng),建立連接和關(guān)閉連接叫做一次連接 可以參考(https://blog.csdn.net/DavidStar1988/article/details/80400020

rxjava

zip 合并observable

其他操作符https://blog.csdn.net/chaoyangsun/article/details/80373203

    創(chuàng)建類型

        concat 將Observable依次發(fā)送

        merge 交錯,不按順序發(fā)送

        ust      原樣發(fā)射

        from    將數(shù)組分成單個依次發(fā)射

        Interval    間隔發(fā)射

        timer 延遲發(fā)射

    轉(zhuǎn)換類型

        map 轉(zhuǎn)換數(shù)據(jù) 比如給我的是url,但是我需要的是bitmap,這時候就用map

        filter 篩選,按條件篩選,比如篩選出非空的url

        flatmap    相對于map,可以多對多,比如在轉(zhuǎn)換數(shù)據(jù)的集合里進行拆分

just 和from區(qū)別: just是設(shè)置什么就返回什么,from是把數(shù)組分成單獨的發(fā)送
https://blog.csdn.net/moonpure/article/details/78402347

retrofit

其實retrofit不是一個網(wǎng)絡(luò)請求庫,它是一個請求庫上面的一個封裝,建立在okhttp上的一個庫,特點就是你可以用注解去構(gòu)建一個網(wǎng)絡(luò)請求,他先是用接口去實現(xiàn)一個帶有注解的類,然后用retrofit的create去創(chuàng)建一個實體,我看了一下源碼,這個create里面是用了動態(tài)代理來實現(xiàn)的他就是通過反射在一個class方法的前后增加邏輯代碼,這些邏輯代碼就是用到okhttp的庫,最后生成一個請求的request,里面設(shè)計感還是很強的,工廠模式,適配器模式還提供了rxjava的支持,和rxjava結(jié)合還是用的很爽的http://www.itdecent.cn/p/a8b98e66b1b8

Glide

和其他圖片加載框架差不多,glide都有三級緩存,但是glide比較強大的是能加載gif,還有g(shù)lide的with方法傳入的context會進行檢查,他會添加一個隱藏的fragment來監(jiān)聽生命周期,達(dá)到自動回收圖片的目的

Volley

volley的封裝比較簡單是輕量級的,volley也支持okhttp,但是volley不支持post大文件數(shù)據(jù)

Dagger

dagger是一個注解處理器,幫助項目解耦少用new關(guān)鍵字,和spring的作用差不多,但是他是編譯期間通過apt插件預(yù)生成一些代碼,而spring是在運行期間,它主要可以幫助你做一些初始化的操作,缺點就是編譯時間邊長了,每次運行要多很長時間http://www.itdecent.cn/p/cc54c5ec9897

事件分發(fā)

// 以ACTION_DOWN事件為例:

  1. 該View的onTouchEvent()返回false
  2. 該View的父ViewGroup收到返回的false
  3. 父ViewGroup會自己嘗試處理事件(調(diào)用自己的onTouchEvent())
  4. 如果父ViewGroup的onTouchEvent()也返回false
  5. 事件會繼續(xù)向上傳遞,直到:
    • 某個父ViewGroup的onTouchEvent()返回true(處理事件)
    • 或傳遞到Activity的onTouchEvent()

數(shù)據(jù)庫增加字段

sqllite只支持增加字段,刪除字段只能重新建表,方法就是把表重命名,新建一張帶有該字段的表,然后復(fù)制數(shù)據(jù)

數(shù)據(jù)庫框架比較

Room, sqlite

數(shù)據(jù)庫性能優(yōu)化

  • 數(shù)據(jù)庫操作基本由三個過程,創(chuàng)建事務(wù),執(zhí)行sql,提交,這三個過程,但是我們批量操作,就變成創(chuàng)建事務(wù),執(zhí)行n個sql,提交,這樣效率會提高很多,

  • 在sql語句數(shù)量比較多的情況下,用stringbuilder代替string拼接,這樣會提高空間分配效率

  • 查詢時根據(jù)需要返回盡量少的字段,可以減少內(nèi)存的消耗

  • 查詢結(jié)束后及時關(guān)閉cursor

  • 如果條件允許的話可以在建表的時候記住columnIndex,它是一個int類型下標(biāo)值,不用每次查詢都去調(diào)用getColumnIndex,這個在數(shù)據(jù)量龐大的查詢條件下會比較節(jié)省時間

  • 調(diào)用數(shù)據(jù)庫的時候要用子線程防止卡ui,但是由于sqllite是不支持多線程并發(fā)訪問的,兩個線程同時插入會拋出異常,雖然是有事務(wù)控制,可以保證數(shù)據(jù)庫的完整性,但是不能保證線程執(zhí)行的準(zhǔn)確性,也就是說有的線程可能會調(diào)用失敗或者請求出現(xiàn)線程繁忙錯誤,所以sqlite最好保證單線程執(zhí)行

  • 一般情況下,sqlite是多進程可以操作的,不會報錯,但是不能保證插入順序,原則上需要在一個進程里去操作,正確的做法是,啟用一個, 單獨的進程通過contentprovider或者其他ipc向其他進程提供接口,通過這個單獨的進程統(tǒng)一操作

ipc

為什么需要多進程:

  • Android對進程的內(nèi)存分配是有限的,用多進程讓核心服務(wù)和UI分離,可以為用戶提供更好的程序穩(wěn)定性,提升用戶體驗 開啟多進程,用多進程分擔(dān)內(nèi)存壓力,用前臺service保證adj的值最小,最不容易回收

  • 內(nèi)存分配 管理內(nèi)存分配的是LMK LowMemoryKiller,通過adb命令proc/pid/com_score_adj可以看到一個應(yīng)用的adj值,值越大,越容易被回收,通常切換到后臺會變大

  • 多進程會出現(xiàn)的問題:

    共享內(nèi)存失效,單例,靜態(tài)變量成員失效,同步鎖失效,application多個,sharepreferce可靠性下降
    
  • 應(yīng)用場景:

    音樂播放器,定位服務(wù)
    
  • 開啟多進程的方式:在四大組件注冊文件中指定 android:process

  • 多進程的通信方式:

    1. Bundle 常用于四大組件通訊

    2. 文件共享,多進程操作同一個文件交換數(shù)據(jù) 但是不支持并發(fā)

    3. Messenger 輕量級的AIDL ,需要基于Handler

    4. Socket

    5. AIDL 寫aidl接口文件,在服務(wù)里通過Binder拿到接口對象傳遞數(shù)據(jù),注冊服務(wù),客戶端綁定服務(wù)轉(zhuǎn)換aidl接口獲取數(shù)據(jù)

    6. ContentProvider 例如我們的應(yīng)用訪問系統(tǒng)的通訊錄數(shù)據(jù)

recycleview

嵌套scrollview卡頓,重新scrollview攔截一下事件

嵌套顯示不全item,外面再包一層relativelayout 增加一個descendantfcusability屬性

布局優(yōu)化

  1. 避免層級太多

  2. 開發(fā)者模式查看是否過度繪制

  3. 使用include標(biāo)簽重用layout

  4. viewstub標(biāo)簽 (調(diào)用的時候才加載布局)

  5. 不要在onDraw中頻繁創(chuàng)建對象和做耗時操作

socket

創(chuàng)建服務(wù)端socket連接對象,指定ip和端口號,子線程進行

監(jiān)聽socket流,獲取服務(wù)端返回數(shù)據(jù)

發(fā)送數(shù)據(jù)也是利用InputStream的write字節(jié)

websocket

是基于類似于http的應(yīng)用層協(xié)義,使用jar包WebSocketClient連接服務(wù)器

Android動畫

  • view動畫 移動,平移,縮放,旋轉(zhuǎn)

  • drawable動畫 幀動畫,一幀一幀的

  • property動畫 view動畫升級版,可以渲染還沒加載的view

Handler機制

Handler創(chuàng)建Looper,Looper創(chuàng)建MessageQueue Looper消息隊列處理者用死循環(huán)不斷去 MessageQueue 消息隊列拿到message然后又調(diào)用handler去處理, 類似于生產(chǎn)者消費者http://www.itdecent.cn/p/87ee9b5206df

性能優(yōu)化

1 anr主線程不能處理耗時操作

2 內(nèi)存溢出,bitmap優(yōu)化

3 內(nèi)存抖動,頻繁創(chuàng)建臨時對象

4 內(nèi)存泄漏

  • 使用LeakCanary檢測:

    運行后會在另外一個Leaks的app中顯示,該庫會監(jiān)聽onDistory方法,把activity實例放在弱引用里實時訪問,找出內(nèi)存泄露的變量和類

  • android studio app profiler工具:

    可以查看當(dāng)前運行app的CPU,內(nèi)存,網(wǎng)絡(luò)的占用和消耗,可以看當(dāng)前頁面所在類的實例,可以調(diào)試內(nèi)存泄漏和占用比例

  • webview引起的內(nèi)存泄露,手動創(chuàng)建,手動銷毀,不要在xml使用

  • 線程銷毀

  • context單例引用

  • handler

  • 弱引用

  • SQLite使用完記得關(guān)閉鏈接

5 ui布局復(fù)雜

6 view重復(fù)繪制

7 懶加載setUserVisibleHint

http://www.itdecent.cn/p/3e44250ca2de

activity啟動模式

standard

   默認(rèn)啟動模式,start多少就開啟多少

singletop

   棧頂唯一,允許有多個實例,但是不允許疊加,通知欄跳轉(zhuǎn)

singleTask

   棧唯一,但是start的時候如果此activity之上有新的activity會被銷毀,會調(diào)用此activity的onNewIntent方法,主界面

singleInstance

   棧唯一,一般用于系統(tǒng)應(yīng)用,launcher

Android 678910 的差異

6.0     運行時權(quán)限,休眠模式,app進入休眠模式會斷開網(wǎng)絡(luò),殺掉一些空置進程

7.0    分屏多任務(wù),VR,通知欄快捷回復(fù),優(yōu)化編輯器減少安裝速度,文件加密

8.0    畫中畫,Notifcation Dots,自適應(yīng)桌面圖標(biāo),后臺進程限制,運行時權(quán)限優(yōu)化,安裝位置來源apk權(quán)限

9.0    WIFI RTT室內(nèi)精準(zhǔn)定位,凹凸屏支持,消息通知優(yōu)化,多攝像頭api,ImageDecoder,神經(jīng)網(wǎng)絡(luò)api,NFC api

10.0  暗黑模式,桌面模式(投影),5Gapi,折疊屏支持,手勢導(dǎo)航,后臺程序位置獲取權(quán)限,神經(jīng)網(wǎng)絡(luò)1.2,文件沙盒

http://www.itdecent.cn/p/88409d6f5795

activity fragment互傳值

// Activity
class MainActivity : AppCompatActivity() {
// Activity 自己的 ViewModel
private val activityViewModel: MainViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    activityViewModel.message.value = "Hello from Activity"
    
    // 添加 Fragment
    supportFragmentManager.beginTransaction()
        .add(R.id.container, FragmentA())
        .commit()
}

}

// Fragment A
class FragmentA : Fragment() {
// 獲取 Activity 的 ViewModel(共享)
private val sharedViewModel: MainViewModel by activityViewModels()
// 獲取 Fragment 自己的 ViewModel
private val fragmentViewModel: FragmentAViewModel by viewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    // 可以訪問 Activity 設(shè)置的數(shù)據(jù)
    println(sharedViewModel.message.value) // 輸出: "Hello from Activity"
    
    // 修改共享數(shù)據(jù)
    sharedViewModel.message.value = "Modified by FragmentA"
}

}

// Fragment B
class FragmentB : Fragment() {
// 同樣獲取 Activity 的 ViewModel
private val sharedViewModel: MainViewModel by activityViewModels()
// Fragment 自己的 ViewModel
private val fragmentViewModel: FragmentBViewModel by viewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    // 看到 FragmentA 修改的數(shù)據(jù)
    println(sharedViewModel.message.value) // 輸出: "Modified by FragmentA"
    
    // Fragment 各自的 ViewModel 互不影響
    println(fragmentViewModel.fragmentData.value) // FragmentB 自己的數(shù)據(jù)
}

}

外部獲取自定義view的寬高

不能直接獲取,view沒有進行onmeasure方法獲取到是0,有兩種方法

——自己調(diào)用view的onmeasure測量

——需要設(shè)置一個監(jiān)聽,View.ViewTreeObserver.addGlobalLayoutLinstener在這個回調(diào)里獲取寬高

hashcode

hashcode是用對象的字段算出來的一個數(shù)字,用來比較兩個對象是否相等,但是他需要和 equals一起使用,當(dāng)hashcode相等的時候比較equals,這樣比較更高效 當(dāng)hashcode相等時兩個對象不一定相等

StringBuffer和StringBuilder

stringbuffer是線程安全,stringbuilder不能多線程訪問,但是stringbuilder速度更快,另外string因為每次都是新建對象,所以string也是線程安全

接口的意義

接口主要為了彌補類不能實現(xiàn)多繼承的缺點,有了接口一個類可以實現(xiàn)多個接口的操作

內(nèi)部類,靜態(tài)內(nèi)部類,局部內(nèi)部類

內(nèi)部類可以隱藏一些外部類的變量和方法,不讓調(diào)用者知道

靜態(tài)內(nèi)部類不依賴外部對象,但是可以指向表達(dá)一種從屬關(guān)系

局部類只是在方法里面使用

設(shè)計模式

  • 單例模式
  • 工廠模式(工廠方法,抽象工廠)
  • 策略模式
  • 代理模式 (動態(tài)代理靜態(tài)代理)
  • 觀察者模式
  • 責(zé)任鏈模式

模塊化組件化與插件化和熱修復(fù)

模塊化是把基礎(chǔ)業(yè)務(wù)分成一個模塊,其他業(yè)務(wù)引用基礎(chǔ)業(yè)務(wù),這些模塊都在同一個工程
組件化是指一個app有多個module,每個module負(fù)責(zé)一部分業(yè)務(wù),每個業(yè)務(wù)組件可以單獨打包也可以做依賴庫,最后打包成為一個apk,
插件化是指一個項目分為一個宿主和多個插件,每個插件是一個apk,最后這個宿主app加載多個apk,可以實現(xiàn)動態(tài)加載
熱修復(fù)是指為一個業(yè)務(wù)或者一個class單獨進行加載,已達(dá)到修復(fù)bug的目的

排序算法

  • 冒泡排序
int a = [2,1,5,9,5]
int temp = 0;
for (int i = 0; i < a.length-1; i++) {
    for (int j = 0;j < a.length-1-i; j++) {
        if (a[j] > a[j+1]) {
            temp = a[j];
            a[j] = a[j+1];
            a[j+1] = temp;
        }
    }
}

原理,像擠跑跑一樣,一個一個擠出來,第二層for循環(huán)每一次選出一個最大值,外面一層for循環(huán)控制第二層循環(huán)的排序范圍

  • 選擇排序


    image.png

    總結(jié),就是把里面的循環(huán)每次找到一個最小值,外面的循環(huán)控制輪詢范圍

glide 和 Picasso的選擇

特性 glide Picasso
gif加載 支持gif加載 不支持
生命周期 支持 不支持
內(nèi)存 根據(jù)image尺寸 full 尺寸
加載時間 慢-先改變尺寸 快-直接加載到內(nèi)存

圖片加載時,傳入Context對象或者fragment對象,glide會生成一個無UI的fragment,因為glide無法從傳入的context中獲取生命周期 通過這個fragment可以拿到傳入context相同的生命周期,從而實現(xiàn)了對生命周期變化做出相同的暫停和銷毀操作

總結(jié):小項目用Picasso,功能簡單,加載速度快,大項目用glide,功能配置豐富,對內(nèi)存優(yōu)化比較好,對于內(nèi)存方面,glide會對不同尺寸的圖片緩存多份緩存,
而Picasso都是同一份緩存,根據(jù)尺寸要求在內(nèi)存中進行resize,所以下載速度Picasso>glide,內(nèi)存加載速度glide> Picasso

activity啟動過程

首先從點擊桌面圖標(biāo)開始,launcher進程通過binder ipc向system service發(fā)起通信startActivity,system service進程的AMS(activity manager service)會判斷app進程是否已經(jīng)創(chuàng)建,若沒有創(chuàng)建則通過binder ipc向zygote通信fork app進程, app進程會通過ipc向ams 發(fā)起通信 請求attachapplication 和得到schedulelancheractivity請求然后和主線程通信,主線程開始調(diào)用activity oncreate app正式啟動

  1. 用戶點擊圖標(biāo)
  2. Launcher → AMS: startActivity() // Binder調(diào)用
  3. AMS檢查進程 → 不存在
  4. AMS → Zygote: fork新進程 // Socket通信
  5. App進程啟動
  6. ActivityThread.main()啟動
  7. App進程 → AMS: attachApplication() // 注冊自己
  8. AMS收到注冊 → 處理attachApplicationLocked()
  9. AMS → App: bindApplication() // 告訴App可以初始化了
  10. App進程收到BIND_APPLICATION消息
  11. handleBindApplication() // 核心!

    ├─ 11.1 創(chuàng)建LoadedApk

    ├─ 11.2 創(chuàng)建Application對象(反射)

    ├─ 11.3 Application.attachBaseContext() // 第一次

    ├─ 11.4 安裝ContentProvider

    │ ├─ 創(chuàng)建所有ContentProvider實例
    ↓ │
    │ └─ ContentProvider.onCreate() // 每個Provider

    └─ 11.5 Application.onCreate() // 第二次
  12. Application初始化完成
  13. AMS查找要啟動的Activity
  14. AMS → App: scheduleLaunchActivity() // 啟動Activity
  15. App進程收到LAUNCH_ACTIVITY消息
  16. handleLaunchActivity() // 核心!

    ├─ 16.1 創(chuàng)建Activity實例(反射)

    ├─ 16.2 Activity.attach() // 關(guān)聯(lián)Context

    ├─ 16.3 Instrumentation.callActivityOnCreate()

    └─ 16.4 Activity.onCreate() // 用戶可見
  17. 后續(xù)生命周期:onStart() → onResume()
  18. 界面顯示

協(xié)成

什么是協(xié)成

協(xié)成是輕量級線程,建立在線程之上,和線程的區(qū)別就是它不會阻塞任務(wù),而是掛起任務(wù),當(dāng)一個任務(wù)出現(xiàn)阻塞的時候這個線程會被掛起,掛起之后這個線程還可以去執(zhí)行其他任務(wù),而這個任務(wù)阻塞結(jié)束后又會被線程執(zhí)行,相當(dāng)于是把線程進行分段,相當(dāng)于用最少的線程做更多的事情,節(jié)約資源,協(xié)成的另外一個好處就是它的調(diào)用是同步的,不需要回調(diào)函數(shù),只需要return回結(jié)果,看上去更簡潔易懂

如何開啟協(xié)成
  • launch
val job = launch {
    repeat(1000) { i ->
        println("job: I'm sleeping $i ...")
        delay(500L)
    }
}
delay(5000L) // 延遲一段時間
println("main: I'm tired of waiting!")
job.cancel() // 取消該作業(yè)
job.join() // 等待作業(yè)執(zhí)行結(jié)束
println("main: Now I can quit.")

launch 返回的是job對象 只能控制協(xié)成狀態(tài),不能返回數(shù)據(jù)結(jié)構(gòu),異步方法需要用suspend修飾

  • async
val time = measureTimeMillis {
    val one = async { doSomethingUsefulOne() }
    val two = async { doSomethingUsefulTwo() }
    println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")

async 返回的是defferred對象,可以控制協(xié)成狀態(tài)可以返回數(shù)據(jù)結(jié)構(gòu),defferred是Job的子類

以上兩種方式都可以用Dispather 指定協(xié)成在那個線程運行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近整理了一波面試題,包括安卓JAVA方面的,目前大廠還是以安卓源碼,算法,以及數(shù)據(jù)結(jié)構(gòu)為主,有一些中小型公司也會...
  • 久違的晴天,家長會。 家長大會開好到教室時,離放學(xué)已經(jīng)沒多少時間了。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,822評論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會,身份的轉(zhuǎn)變要...
    余生動聽閱讀 10,857評論 0 11
  • 在妖界我有個名頭叫胡百曉,無論是何事,只要找到胡百曉即可有解決的辦法。因為是只狐貍大家以訛傳訛叫我“傾城百曉”,...
    貓九0110閱讀 3,715評論 7 3
  • 彩排完,天已黑
    劉凱書法閱讀 4,479評論 1 3

友情鏈接更多精彩內(nèi)容