xUtils使用詳細介紹

来源:http://www.cnblogs.com/favour/archive/2017/06/03/6936385.html
-Advertisement-
Play Games

xUtils3使用詳解 一、xUtils簡介: xUtils是基於Afinal開發的目前功能比較完善的一個Android開源框架,官網:https://github.com/wyouflf/xUtils3 xUtils 包含了orm, http(s), image, view註解, 但依然很輕量級( ...


xUtils3使用詳解


一、xUtils簡介:

xUtils是基於Afinal開發的目前功能比較完善的一個Android開源框架,官網:https://github.com/wyouflf/xUtils3

  • xUtils 包含了orm, http(s), image, view註解, 但依然很輕量級(246K), 並且特性強大, 方便擴展:
  1. 穩定的基石: AbsTask和統一的回調介面Callback, 任何異常, 即使你的回調方法實現有異常都會進入onError, 任何情況下onFinished總會讓你知道任務結束了.
  2. 基於高效穩定的orm工具, http模塊得以更方便的實現cookie(支持domain, path, expiry等特性)和 緩存(支持Cache-Control, Last-Modified, ETag等特性)的支持.
  3. 有了強大的http及其下載緩存的支持, image模塊的實現相當的簡潔, 並且支持回收被view持有, 但被Mem Cache移除的圖片, 減少頁面回退時的閃爍..
  4. view註解模塊僅僅400多行代碼卻靈活的支持了各種View註入和事件綁定, 包括擁有多了方法的listener的支持.

其他特性:

  • 支持超大文件(超過2G)上傳
  • 更全面的http請求協議支持(11種謂詞)
  • 擁有更加靈活的ORM, 和greenDao一致的性能
  • 更多的事件註解支持且不受混淆影響...
  • 圖片綁定支持gif(受系統相容性影響, 部分gif文件只能靜態顯示), webp; 支持圓角, 圓形, 方形等裁剪, 支持自動旋轉...
  • 從3.5.0開始不再包含libwebpbackport.so, 需要在Android4.2以下設備相容webp的請使用3.4.0版本.

    總的來說。xutils主要有4個模塊:註解模塊,網路模塊,圖片載入模塊,資料庫模塊。

    二、使用前配置

    1.使用Gradle構建時添加一下依賴即可:

    compile 'org.xutils:xutils:3.4.0'

    或在直接在android studio引入xutils3

2.需要的許可權:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

三、初始化過程:

新建一個類MyApplication繼承Application:
//初始化
public class MyApplication extends Application {
   public void onCreate() {
    super.onCreate();
    x.Ext.init(this);
    x.Ext.setDebug(true); //是否輸出debug日誌,開啟debug會影響性能。
    }
}
在Manifest文件中註冊MyApplication
<application

android:name=".MyApp" //註冊MyApplication
...
</application

四、註解模塊

註解(Annotation)為我們在代碼中添加信息提供了一種形式化的方法,是我們可以在稍後某個時刻方便地使用這些數據(通過 解析註解 來使用這些數據)

1.@ContentView:

載入當前的Activity佈局時 將@ContentView加入到Activity的上方

2.@ViewInject

View註解的作用是代替我們寫了findViewById這行代碼,一般用於敏捷開發。

3.@Event事件註解

處理控制項的各種響應事件,需要註意的是:
****
* 1. 方法必須私有限定,
* 2. 方法參數形式必須和type對應的Listener介面一致.
* 3. 註解參數value支持數組: value={id1, id2, id3}
* 4. type預設View.OnClickListener.class,即可故可以不寫,直接寫@Event(R.id.bt1)如果你想實現其餘點擊事件效果,只需要把type值進行修改

例:MainActivity

@ContentView(R.layout.activity_main)//載入佈局xml
public class MainActivity extends AppCompatActivity {
    // view註解要求必須提供id,以使代碼混淆不受影響。
    // 代價是增加了一次反射,每個控制項都會。而反射是比較犧牲性能的做法,所以使用View註解算是有利有弊吧。
    @ViewInject(R.id.tv1)
    private TextView tv1;


    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    x.view().inject(this); //綁定註解
    }
    
    //Event事件註解 ,點擊bt1後彈出bt1測試
    @Event(value = {R.id.bt1},type = View.OnClickListener.class) 
    //方法需要用private
    private void onTest1click(View view){

    Toast.makeText(this,"bt1測試",Toast.LENGTH_LONG).show();
    }
    //長按事件
    @Event(value = R.id.Long,type = View.OnLongClickListener.class)
    private boolean testOnLongClickListener(View v){
    Toast.makeText(this,"btLong測試",Toast.LENGTH_LONG).show();  
    return true;
    }
}

例:fragment

@ContentView(R.layout.fragment_base)
public class BaseFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return x.view().inject(this, inflater, container);
    }
    @Override
    public void onViewCreated(View v, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(v, savedInstanceState);
    }
}

五、網路模塊

xUtils3網路模塊大大方便了在實際開發中網路模塊的開發,xUtils3網路模塊大致包括GET請求、POST請求、如何使用其他請求方式、上傳文件、下載文件、使用緩存等功能。
Get請求
@Event(value = {R.id.bt2},type = View.OnClickListener.class)//註解
private void onTestGet(View view){
    String url ="http://10.203.0.4:8080/login"
    RequestParams params = new RequestParams(url);
    //params.setSslSocketFactory(...); // 設置ssl
    
    params.addQueryStringParameter("username","abc");
    params.addQueryStringParameter("password","123");
    x.http().get(params, new Callback.CommonCallback<String>() {

        public void onSuccess(String result) {
            Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
            Log.i("JAVA", "onSuccess result:" + result);

        }
        //請求異常後的回調方法
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        //主動調用取消請求的回調方法
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {

        }
    });
   
}
Post請求
@Event(R.id.bt2)
private void onTestPost(View v) {
    String url = "http://10.203.0.4:8080/login";
    RequestParams params = new RequestParams(url);
    params.addParameter("username", "abc");
    params.addParameter("password", "123");
    x.http().request(HttpMethod.PUT, params, new Callback.CommonCallback<String>() {
        @Override
        public void onSuccess(String result) {
        Toast.makeText(x.app(),result,Toast.LENGTH_LONG).show();
        }
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {
        }
    });
}
使用緩存
@Event(R.id.cache)
private void cache(View v) {
RequestParams params = new RequestParams(url);
params.setCacheMaxAge(1000*60); //為請求添加緩存時間
Callback.Cancelable cancelable = x.http().get(params, new Callback.CacheCallback<string>() {
    @Override
    public void onSuccess(String result) {
        Log.i("JAVA","onSuccess:"+result);
    }
    @Override
    public void onError(Throwable ex, boolean isOnCallback) {
    }
    @Override
    public void onCancelled(CancelledException cex) {
    }
    @Override
    public void onFinished() {
    }
    //result:緩存內容
    @Override
    public boolean onCache(String result) {
        //在setCacheMaxAge設置範圍(上面設置的是60秒)內,如果再次調用GET請求,
        //返回true:緩存內容被返回,相信本地緩存,返回false:緩存內容被返回,不相信本地緩存,仍然會請求網路
        Log.i("JAVA","cache:"+result);
        return true;
    }
});
上傳文件
@Event(R.id.upload)
private void upload(View v){
String path="/mnt/sdcard/Download/icon.jpg";
RequestParams params = new RequestParams(url);
params.setMultipart(true);
params.addBodyParameter("file",new File(path));
x.http().post(params, new Callback.CommonCallback<string>() {
    @Override
    public void onSuccess(String result) {
    }
    @Override
    public void onError(Throwable ex, boolean isOnCallback) {
    }
    @Override
    public void onCancelled(CancelledException cex) {
    }
    @Override
    public void onFinished() {
    }
});
下載文件
@Event(R.id.download)
private void download(View v){
url = "http://10.203.0.4:8080/server/nfctest.apk";
RequestParams params = new RequestParams(url);
//自定義保存路徑,Environment.getExternalStorageDirectory():SD卡的根目錄
params.setSaveFilePath(Environment.getExternalStorageDirectory()+"/myapp/");
//自動為文件命名
params.setAutoRename(true);
x.http().post(params, new Callback.ProgressCallback<file>() {
    @Override
    public void onSuccess(File result) {
        //apk下載完成後,調用系統的安裝方法
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(result), "application/vnd.android.package-archive");
        startActivity(intent);
    }
    @Override
    public void onError(Throwable ex, boolean isOnCallback) {
    }
    @Override
    public void onCancelled(CancelledException cex) {
    }
    @Override
    public void onFinished() {
    }
    //網路請求之前回調
    @Override
    public void onWaiting() {
    }
    //網路請求開始的時候回調
    @Override
    public void onStarted() {
    }
    //下載的時候不斷回調的方法
    @Override
    public void onLoading(long total, long current, boolean isDownloading) {
        //當前進度和文件總大小
        Log.i("JAVA","current:"+ current +",total:"+total); 
    }
});



六、圖片載入模塊

xUtils3圖片模塊,重點在於載入圖片的4個bind方法,loadDrawable與loadFIle用法和ImageOptions用法

bind的幾個方法

void bind(ImageView view, String url);

void bind(ImageView view, String url, ImageOptions options);

void bind(ImageView view, String url, Callback.CommonCallback<Drawable> callback);

void bind(ImageView view, String url, ImageOptions options, Callback.CommonCallback<Drawable> callback);

Callback.Cancelable loadDrawable(String url, ImageOptions options, Callback.CommonCallback<Drawable> callback);

Callback.Cancelable loadFile(String url, ImageOptions options, Callback.CacheCallback<File> callback);
1.首先獲取ImageView控制項
@ViewInject(R.id.iv1)
ImageView image01;
@ViewInject(R.id.iv2)
ImageView image02;
...
2.定義圖片網路地址或本地地址
String[] urls = {
        "http://img4.imgtn.bdimg.com/it/u=3182769660,1810895318&fm=23&gp=0.jpg",
        "http://img2.imgtn.bdimg.com/it/u=1278435851,1308167727&fm=23&gp=0.jpg",
        "http://img2.3lian.com/2014/f4/199/d/6.jpg",
        "http://pic1.win4000.com/wallpaper/4/584b9ea3a511c.jpg"
        ...


};  
3,通過ImageOptions.Builder().set方法設置圖片的屬性 然後通過bind方法載入圖片,顯示圖片方法setImg()如下:
private void setImg() {
    /**
     * 通過ImageOptions.Builder().set方法設置圖片的屬性
     */
    ImageOptions options = new ImageOptions.Builder().setFadeIn(true).build(); //淡入效果
    //ImageOptions.Builder()的一些其他屬性:

    //.setCircular(true) //設置圖片顯示為圓形
    //.setSquare(true) //設置圖片顯示為正方形
    //setCrop(true).setSize(200,200) //設置大小
    //.setAnimation(animation) //設置動畫
    //.setFailureDrawable(Drawable failureDrawable) //設置載入失敗的動畫
    //.setFailureDrawableId(int failureDrawable) //以資源id設置載入失敗的動畫
    //.setLoadingDrawable(Drawable loadingDrawable) //設置載入中的動畫
    //.setLoadingDrawableId(int loadingDrawable) //以資源id設置載入中的動畫
    //.setIgnoreGif(false) //忽略Gif圖片
    //.setParamsBuilder(ParamsBuilder paramsBuilder) //在網路請求中添加一些參數
    //.setRaduis(int raduis) //設置拐角弧度
    //.setUseMemCache(true) //設置使用MemCache,預設true

    /**
     * 載入圖片的4個bind方法
     */
    x.image().bind(image01, urls[0]);

    x.image().bind(image02, urls[1], options);

    x.image().bind(image03, urls[2], options, new Callback.CommonCallback<Drawable>() {
        @Override
        public void onSuccess(Drawable result) {
        }
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {
        }
    });
    x.image().bind(image04, urls[3], options, new Callback.CommonCallback<Drawable>() {
        @Override
        public void onSuccess(Drawable result) {
        }
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {
        }
    });

    /**
     * loadDrawable()方法載入圖片
     */
    Callback.Cancelable cancelable = x.image().loadDrawable(urls[4], options, new Callback.CommonCallback<Drawable>() {
        @Override
        public void onSuccess(Drawable result) {
            image05.setImageDrawable(result);
        }
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {
        }
    });
    //主動取消loadDrawable()方法
    //cancelable.cancel();

    /**
     * loadFile()方法
     * 應用場景:當我們通過bind()或者loadDrawable()方法載入了一張圖片後,
     * 它會保存到本地文件中,那當我需要這張圖片時,就可以通過loadFile()方法進行查找。
     * urls[0]:網路地址
     */
    x.image().loadFile(urls[0],options,new Callback.CacheCallback<File>(){
        @Override
        public boolean onCache(File result) {
            //在這裡可以做圖片另存為等操作
            Log.i("JAVA","file:"+result.getPath()+result.getName());
            return true; //相信本地緩存返回true
        }
        @Override
        public void onSuccess(File result) {
            Log.i("JAVA","file");
        }
        @Override
        public void onError(Throwable ex, boolean isOnCallback) {
        }
        @Override
        public void onCancelled(CancelledException cex) {
        }
        @Override
        public void onFinished() {
        }
    });
}

七:資料庫模塊的使用

首先進行配置DaoConfig:

DbManager.DaoConfig daoConfig = new DbManager.DaoConfig()
        //設置資料庫名,預設xutils.db
        .setDbName("myapp.db")
        // 不設置dbDir時, 預設存儲在app的私有目錄.
        .setDbDir(new File("/sdcard")) // "sdcard"的寫法並非最佳實踐, 這裡為了簡單, 先這樣寫了.
        .setDbVersion(1)//資料庫版本

        //設置是否允許事務,預設true
        //.setAllowTransaction(true)

        //設置表創建的監聽
        .setTableCreateListener(new DbManager.TableCreateListener(){

            @Override
            public void onTableCreated(DbManager db, TableEntity<?> table) {
                Log.i("JAVA", "onTableCreated:" + table.getName());
            }
        })

        //設置資料庫更新的監聽
        .setDbUpgradeListener(new DbManager.DbUpgradeListener() {
            @Override
            public void onUpgrade(DbManager db, int oldVersion, int newVersion) {

            }
        })
        //設置資料庫打開的監聽
        .setDbOpenListener(new DbManager.DbOpenListener() {
            @Override
            public void onDbOpened(DbManager db) {
                //開啟資料庫支持多線程操作,提升性能
                db.getDatabase().enableWriteAheadLogging();
            }
        });
DbManager db = x.getDb(daoConfig);
然後創建資料庫表Person的實體類:
/**
 * onCreated = "sql" sql:當第一次創建表需要插入數據時候在此寫sql語句例:CREATE UNIQUE INDEX index_name ON person(id,name)
 */
@Table(name ="person",onCreated = "")
public class Person {
    /**
    * name = "id":資料庫表中的一個欄位
    * isId = true:是否是主鍵
    * autoGen = true:是否自動增長
     * property = "NOT NULL":添加約束
    */  
    @Column(name = "id",isId = true,autoGen = true,property = "NOT NULL")
    private int id;
    @Column(name = "c_name")
    private String name;

    public Person(String name) {
        this.name = name;
    }

    //預設的構造方法必須寫出,如果沒有,這張表是創建不成功的
    public Person() {

    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
資料庫的創建與刪除以及數據的增刪改查
資料庫的創建
//資料庫的創建
@Event(R.id.create_db)
private void createDB(View v) throws DbException {
    //用集合向Person表中插入多條數據
    ArrayList<Person> person = new ArrayList<>();
    person.add(new Person("張三"));
    person.add(new Person("李四"));
    person.add(new Person("趙六"));

    //db.save()方法不僅可以插入單個對象,還能插入集合
    db.save(person);
}
資料庫的刪除
//刪除資料庫
@Event(R.id.del_db)
private void delDB(View v) throws DbException {

    db.dropDb();
}
表的刪除
@Event(R.id.del_table)
private void delTable(View v) throws DbException {
    db.dropTable(Person.class);
}
查詢數據
@Event(R.id.select_table)
private void selelctDB(View v) throws DbException {
    //查詢資料庫表中第一條數據
    Person first = db.findFirst(Person.class);
    Log.i("JAVA",first.toString());

    //findAll():查詢所有結果
    List<Person> personAll =db.findAll(Person.class);
    List<String > list = new ArrayList<String>();
    for(int i=0;i<personAll.size();i++){
        list.add(personAll.get(i).toString());
    }
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,list);
    lv1.setAdapter(adapter); 

    //添加查詢條件進行查詢
    WhereBuilder b = WhereBuilder.b();
    b.and("id",">",2); //構造修改的條件
    b.and("id","<",4);
    List<Person> all = db.selector(Person.class).where(b).findAll();
    //第二種寫法:
    List<Person> all2 = db.selector(Person.class).where("id",">",2).and("id","<",4).findAll();
    for(Person person :all){
        Log.i("JAVA",person.toString());
    }
}
修改數據
//修改表中數據
@Event(R.id.update_table)
private void updateTable(View v) throws DbException {
    //第一種寫法:
    Person first = db.findFirst(Person.class);
    first.setName("張三01");
    db.update(first, "c_name"); //c_name:表中的欄位名
    //第二種寫法:
    WhereBuilder b = WhereBuilder.b();
    b.and("id", "=", first.getId()); //構造修改的條件
    KeyValue name = new KeyValue("c_name", "張三02");
    db.update(Person.class, b, name);

    //第三種寫法:
    first.setName("張三修改");
    db.saveOrUpdate(first);
    Toast.makeText(this,"修改成功",Toast.LENGTH_LONG).show();
}
刪除數據
@Event(R.id.del_table_data)
private void delTableData(View v) throws DbException {
    //第一種寫法:
    db.delete(Person.class); //child_info表中數據將被全部刪除
    //第二種寫法,添加刪除條件:
    WhereBuilder b = WhereBuilder.b();
    b.and("id",">",2); //構造修改的條件
    b.and("id","<",4);
    db.delete(Person.class, b);
}



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前面的話 幾年前,對於學習NodeJS可能還有所遲疑,怕分散了前端學習的精力。但到了現在,如果不學習nodeJS,前端的學習卻可能無法再有所進展。技術的進步就是這麼殘酷。對新技術觀望的時候,該技術已經大行其道了。本文將介紹nodeJS的基礎知識 語言選擇 Ryan Dahl是一名資深的C/C++程式 ...
  • 前面的話 一般地,我們使用構建工具來完成項目的自動化操作。本文主要介紹如何使用nodeJS來實現簡單的項目結構構建和文件合併 項目構建 假設,最終實現的項目名稱為'test',結構如下圖所示 那麼,首先需要先設置一個JSON對象來保存要創建的目錄結構 目錄結構的創建邏輯如下 文件合併 假設,目標是合 ...
  • 雖然新浪微博APP自己沒有提供下載微博視頻的功能,但我們可以藉助第三方工具來下載微博視頻。網上很多是要安裝軟體到電腦上才能用的,但如果我們想在手機上用,就用不了。 所以今天分享一個在手機上也能下載微博和秒拍視頻的方法。 下載新浪微博視頻和秒拍視頻的方法: 1. 打開新浪微博APP,找到想要下載的視頻 ...
  • [1]概述 [2]底層操作 [3]File操作 [4]目錄操作 [5]遍歷目錄 ...
  • 應用的平臺環境:安卓webview; 涉及的技術點: (1) <input type="file" > :在開發中,安卓webview預設點擊無法調用文件選擇與相機拍照(其他的設備ios等瀏覽器沒有此問題),需要讓安卓開發同學在代碼調整即可; (2) 點擊選擇圖片後如何展示在頁面上呢?很多開發人員估 ...
  • Android之自定義View學習(一) Canvas常用方法: 圖片來源 github地址:https://github.com/SiberiaDante/DrawView ...
  • <ion-slide-box>屬性中迴圈播放:dose-continue=‘true’,但是在項目遇到這樣一個問題,從後臺獲取數據後將數據ng-repeat到<ion-slide>中,發現迴圈播放失效了,後來在外網中找到了一個解決方法。 $ionicSlideBoxDelegate.update() ...
  • 1.概述 Android4.4以上開始使用ART虛擬機,在此之前我們一直使用的Dalvik虛擬機,那麼為什麼Google突然換了Android運行的虛擬機呢?答案只有一個:ART虛擬機更優秀。 2.Dalvik vs ARTDalvik Android4.4及以前使用的都是Dalvik虛擬機,我們知 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...