ContentProvider功能變數名稱替換小工具

来源:http://www.cnblogs.com/dingzq/archive/2016/11/17/6073086.html
-Advertisement-
Play Games

開發項目功能變數名稱想怎麼換就怎麼換,就是這麼任性! 這是一個很有意思的小工具! 這是一個方便開發人員和測試人員的小工具!! 吐槽: 一直在做Android開發,一直總有一個問題存在:做自己公司的apk開發時,線上包和測試包不可兼得~總是在 卸載、安裝、卸載、安裝。。。的迴圈操作。很是麻煩,而且另外一個不得 ...


開發項目功能變數名稱想怎麼換就怎麼換,就是這麼任性!

這是一個很有意思的小工具!

這是一個方便開發人員和測試人員的小工具!!

吐槽:

一直在做Android開發,一直總有一個問題存在:做自己公司的apk開發時,線上包和測試包不可兼得~總是在 卸載、安裝、卸載、安裝。。。的迴圈操作。很是麻煩,而且另外一個不得不正視的問題就是:只要跟服務端人員進行聯調時,就得修改項目中的測試功能變數名稱,重新打包,也是夠麻煩的。最近報名了公司的一個服務,就不得不使用線上包了,被逼無奈想起了這個小設計。

原理:

使用ContentProvider數據共用~

展示圖:

 

 

 設計思路及源碼解析:

 1.前期準備

a.ContentProvider在android中的作用是對外共用數據, 也就是說你可以通過ContentProvider把應用中的數據共用給其他應用訪問,其他應用可以通過ContentProvider對你應用中的數據進行添刪改查。

當應用需要通過ContentProvider對外共用數據時,第一步需要繼承ContentProvider並重寫下麵方法:

 

public class PersonContentProvider extends ContentProvider{
    public boolean onCreate()
    public Uri insert(Uri uri, ContentValues values)
    public int delete(Uri uri, String selection, String[] selectionArgs)
    public int update(Uri uri, ContentValues values, String selection,         String[] selectionArgs)
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
    public String getType(Uri uri)
}    

 

b.第二步需要在AndroidManifest.xml使用對該ContentProvider進行配置,為了能讓其他應用找到該ContentProvider ,ContentProvider採用了authorities(主機名/功能變數名稱)對它進行唯一標識,你可以把ContentProvider看作是一個網 站(想想,網站也是提供數據者),authorities 就是他的功能變數名稱

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xc1217.contentprovider">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".activity.UrlListActivity"
android:theme="@style/AppTheme.NoActionBar">
</activity>

<provider android:name=".db.MyContentProvider"
android:authorities="com.xc1217.contentprovider.myprovider"
android:exported="true"/>
</application>

</manifest>
2.資料庫設計
/**
 * Created by ding on 2016/11/15.
 */
public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String DBNAME = "1217provider.db"; //資料庫名稱
    private static final int DBVER = 1;//資料庫版本

    public DBOpenHelper(Context context) {
        super(context, DBNAME, null, DBVER);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // id 主鍵id,  url 路徑   selected 1 選中,0 未選中
        String sql = "CREATE TABLE student (id integer primary key autoincrement, url varchar(500), selected int)";
        String sql2 = "CREATE TABLE coach (id integer primary key autoincrement, url varchar(500), selected int)";
        db.execSQL(sql);//執行有更改的sql語句
        db.execSQL(sql2);
        initDb(db);
    }

    private void initDb(SQLiteDatabase db) {
        String sql = "INSERT INTO student VALUES (1,'http://www.1217.com/', 0)";
        String sq2 = "INSERT INTO student VALUES (2,'http://www.1217.com/', 1)";
        String sq3 = "INSERT INTO student VALUES (3,'http://www.1217.com/', 0)";
        String sq4 = "INSERT INTO student VALUES (4,'http://www.1217.com/', 0)";
        db.execSQL(sql);
        db.execSQL(sq2);
        db.execSQL(sq3);
        db.execSQL(sq4);
        initAddDbCoach(db);
    }

    private void initAddDbCoach(SQLiteDatabase db) {
        String sql = "INSERT INTO coach VALUES (1,'http://www.1217.com/', 0)";
        String sq2 = "INSERT INTO coach VALUES (2,'http://www.1217.com/', 1)";
        String sq3 = "INSERT INTO coach VALUES (3,'http://www.1217.com/', 0)";
        String sq4 = "INSERT INTO coach VALUES (4,'http://www.1217.com/', 0)";
        db.execSQL(sql);
        db.execSQL(sq2);
        db.execSQL(sq3);
        db.execSQL(sq4);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
        db.execSQL("DROP TABLE IF EXISTS student");
        db.execSQL("DROP TABLE IF EXISTS coach");
        onCreate(db);
    }

}

 

3.繼承ContentProvider並重寫方法

 

/**
 * Created by ding on 2016/11/15.
 */
public class MyContentProvider extends ContentProvider {
    private DBOpenHelper dbOpenHelper;
    //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼
    private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    private static final int STUDENTS = 1;
    private static final int STUDENT = 2;
    private static final int COACHS = 3;
    private static final int COACH = 4;

    static {
        //如果match()方法匹配content://com.xc1217.contentprovider.myprovider/student路徑,返回匹配碼為1
        MATCHER.addURI("com.xc1217.contentprovider.myprovider", "student", STUDENTS);
        //如果match()方法匹配content://com.xc1217.contentprovider.myprovider/student/123路徑,返回匹配碼為2
        MATCHER.addURI("com.xc1217.contentprovider.myprovider", "student/#", STUDENT);//#號為通配符
        MATCHER.addURI("com.xc1217.contentprovider.myprovider", "coach", COACHS);
        MATCHER.addURI("com.xc1217.contentprovider.myprovider", "coach/#", COACH);//#號為通配符
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        int count = 0;
        long id = 0;
        String where = "";
        switch (MATCHER.match(uri)) {
            case STUDENTS:
                count = db.delete("student", selection, selectionArgs);
                return count;
            case STUDENT:
                //ContentUris類用於獲取Uri路徑後面的ID部分
                id = ContentUris.parseId(uri);
                where = "id = " + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                count = db.delete("student", where, selectionArgs);
                return count;
            case COACHS:
                count = db.delete("coach", selection, selectionArgs);
                return count;
            case COACH:
                //ContentUris類用於獲取Uri路徑後面的ID部分
                id = ContentUris.parseId(uri);
                where = "id = " + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                count = db.delete("coach", where, selectionArgs);
                return count;
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
        }
    }

    /**
     * 該方法用於返回當前Url所代表數據的MIME類型。
     * 如果操作的數據屬於集合類型,那麼MIME類型字元串應該以vnd.android.cursor.dir/開頭
     * 如果要操作的數據屬於非集合類型數據,那麼MIME類型字元串應該以vnd.android.cursor.item/開頭
     */
    @Override
    public String getType(Uri uri) {
        switch (MATCHER.match(uri)) {
            case STUDENTS:
                return "vnd.android.cursor.dir/student";

            case STUDENT:
                return "vnd.android.cursor.item/student";
            case COACHS:
                return "vnd.android.cursor.dir/coach";

            case COACH:
                return "vnd.android.cursor.item/coach";

            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        long rowid = 0;
        Uri insertUri = null;//得到代表新增記錄的Uri
        switch (MATCHER.match(uri)) {
            case STUDENTS:
                rowid = db.insert("student", "url", values);
                insertUri = ContentUris.withAppendedId(uri, rowid);//得到代表新增記錄的Uri
                this.getContext().getContentResolver().notifyChange(uri, null);
                return insertUri;
            case COACHS:
                rowid = db.insert("coach", "url", values);
                insertUri = ContentUris.withAppendedId(uri, rowid);//得到代表新增記錄的Uri
                this.getContext().getContentResolver().notifyChange(uri, null);
                return insertUri;

            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
        }
    }

    @Override
    public boolean onCreate() {
        this.dbOpenHelper = new DBOpenHelper(this.getContext());
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder) {
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        long id = 0;
        String where = null;
        switch (MATCHER.match(uri)) {
            case STUDENTS:
                return db.query("student", projection, selection, selectionArgs, null, null, sortOrder);
            case STUDENT:
                id = ContentUris.parseId(uri);
                where = "id = " + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                return db.query("student", projection, where, selectionArgs, null, null, sortOrder);
            case COACHS:
                return db.query("coach", projection, selection, selectionArgs, null, null, sortOrder);
            case COACH:
                id = ContentUris.parseId(uri);
                where = "id = " + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                return db.query("coach", projection, where, selectionArgs, null, null, sortOrder);
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        int count = 0;
        long id = 0;
        String where = null;
        switch (MATCHER.match(uri)) {
            case STUDENTS:
                count = db.update("student", values, selection, selectionArgs);
                return count;
            case STUDENT:
                id = ContentUris.parseId(uri);
                where = "id = " + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                count = db.update("student", values, where, selectionArgs);
                return count;
            case COACHS:
                count = db.update("coach", values, selection, selectionArgs);
                return count;
            case COACH:
                id = ContentUris.parseId(uri);
                where = "id = " + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                count = db.update("coach", values, where, selectionArgs);
                return count;
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
        }
    }
}

 

4.MainActivity. java
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        findViewById(R.id.lay_student).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent intent = new Intent(MainActivity.this, UrlListActivity.class);
                intent.putExtra("table", "student");
                startActivity(intent);
            }
        });
        findViewById(R.id.lay_coach).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, UrlListActivity.class);
                intent.putExtra("table", "coach");
                startActivity(intent);
            }
        });

    }
}
5.UrlListActivity.java
public class UrlListActivity extends AppCompatActivity {
    private static final String TAG = "UrlListActivity";
    String uriString = "content://com.xc1217.contentprovider.myprovider/";
    private String table = "";
    private List<UrlBean> mList = new ArrayList<UrlBean>();
    private ListView listView;
    private int position;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url_list);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        Intent intent = getIntent();
        if (intent != null) {
            table = intent.getStringExtra("table");
            if (TextUtils.isEmpty(table))
                return;
            setTitle(table);
            uriString = uriString + table;
        }
        initUI();
        getUrlList();

    }

    private void initUI() {
        listView = (ListView) findViewById(R.id.list_url);

        findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    showAddPop();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
        });
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                position = i;
                showClickPop();
            }
        });
    }

    private void showAddPop() {
        final EditText editText = new EditText(this);
        editText.setText("http://www.1217.com/");
        editText.setHint("http://www.1217.com/");
        final AlertDialog alertDialog = new AlertDialog.Builder(this).
                setTitle("添加")
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                    }
                })
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String url = editText.getText().toString();
                        insertUrl(url);
                    }
                }).setView(editText).create();
        alertDialog.show();
        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View
                .OnClickListener() {
            @Override
            public void onClick(View v) {
                String url = editText.getText().toString();
                if (TextUtils.isEmpty(url)) {
                    Toast.makeText(UrlListActivity.this, "不能為空", Toast.LENGTH_SHORT).show();
                    return;
                }
                insertUrl(url);
                alertDialog.dismiss();
                getUrlList();
            }
        });
    }

    private void showClickPop() {
        final String[] arrayFruit = new String[]{"選擇", "刪除"};

        Dialog alertDialog = new AlertDialog.Builder(this).
                setTitle("編輯")
                .setItems(arrayFruit, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        switch (which) {
                            case 0:
                                for (int i = 0; i < mList.size(); i++) {
                                    UrlBean urlBean = mList.get(i);
                                    urlBean.selected = (position == i ? 1 : 0);
                                    update(urlBean);
                                }
                                UrlAdapter urlAdapter = new UrlAdapter(UrlListActivity.this, mList);
                                listView.setAdapter(urlAdapter);
                                break;
                            case 1:
                                int id = mList.get(position).id;
                                deleteById(id);
                                getUrlList();
                                break;
                            default:
                                break;
                        }

                    }
                }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                    }
                }).
                        create();
        alertDialog.show();
    }

    //往內容提供者添加數據
    public void insertUrl(String url) {
        try {
            ContentResolver contentResolver = this.getContentResolver();
            Uri insertUri = Uri.parse(uriString);
            ContentValues values = new ContentValues();
            values.put("url", url);
            values.put("selected", 0);
            Uri uri = contentResolver.insert(insertUri, values);
            Log.i(TAG, uri.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //更新內容提供者中的數據
    public void update(UrlBean urlBean) {
        try {
            ContentResolver contentResolver = this.getContentResolver();
            Uri updateUri = Uri.parse(uriString + "/" + urlBean.id);
            ContentValues values = new ContentValues();
            values.put("url", urlBean.url);
            values.put("selected", urlBean.selected);
            contentResolver.update(updateUri, values, null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //從內容提供者中刪除數據
    public void deleteById(Integer id) {
        try {
            ContentResolver contentResolver = this.getContentResolver();
            Uri deleteUri = Uri.parse(uriString + "/" + id);
            contentResolver.delete(deleteUri, null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //獲取內容提供者中的數據
    public void getUrlList() {
        try {
            ContentResolver contentResolver = this.getContentResolver();
            Uri selectUri = Uri.parse(uriString);
            Cursor cursor = contentResolver.query(selectUri, null, null, null, null);
            if (cursor == null)
                return;
            mList.clear();
            while (cursor.moveToNext()) {
                int id = cursor.getInt(cursor.getColumnIndex("id"));
                String url = cursor.getString(cursor.getColumnIndex("url"));
                int selected = cursor.getInt(cursor.getColumnIndex("selected"));
                Log.i(TAG, "id=" + id + ",url=" + url + ",selected=" + selected);
                UrlBean urlBean = new UrlBean(id, url, selected);
                mList.add(urlBean);
            }
            UrlAdapter urlAdapter = new UrlAdapter(this, mList);
            listView.setAdapter(urlAdapter);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
6.UrlAdapter.java
public class UrlAdapter extends BaseAdapter {
    private Context mContext;
    private List<UrlBean> mList;

    public UrlAdapter(Context c, List<UrlBean> l) {
        // TODO Auto-generated constructor stub
        mContext = c;
        mList = l;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mList.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return mList.get(arg0);
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public View getView(final int i, View view, ViewGroup arg2) {
        ViewHoldel holdel;
        if (view == null) {
            holdel = new ViewHoldel();
            view = LayoutInflater.from(mContext).inflate(R.layout.url_item,
                    null);
            holdel.tvContent = (TextView) view.findViewById(R.id.tv_content);
            holdel.imageView = (ImageView) view.findViewById(R.id.imv_right);
            view.setTag(holdel);
        } else {
            holdel = (ViewHoldel) view.getTag();
        }
        holdel.tvContent.setText(mList.get(i).url);
        if (mList.get(i).selected == 1) {
            holdel.imageView.setVisibility(View.VISIBLE);
        } else {
            holdel.imageView.setVisibility(View.GONE);
        }

        return view;
    }

    class ViewHoldel {
        TextView tvContent;
        ImageView imageView;
    }

}
7.url_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:padding="@dimen/activity_horizontal_margin"
              android:orientation="horizontal">

    <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text=",,"
            android:textSize="15sp"/>
    <ImageView
            android:id="@+id/imv_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/icon_true_big"/>
</LinearLayout>

  

重點來了!!!

開發人員接入代碼,替換功能變數名稱:

代碼加入到 Application   初始化方法中;根據需要修改下代碼即可。

private void changeServerHostFromProvider() {
    Uri uri = Uri.parse("content://com.xc1217.contentprovider.myprovider/student");
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null) {
        while (cursor.moveToNext()) {
            String url = cursor.getString(cursor.getColumnIndex("url"));
            int selected = cursor.getInt(cursor.getColumnIndex("selected"));// 1 選中,否則未選中
            if (selected == 1 && !TextUtils.isEmpty(url)) {
                Urls.BASE_URL_TEST = url;
                Urls.BASE_URL_ONLINE = url;
                
                return;
            }
        }
        cursor.close();
    }
}

 


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

-Advertisement-
Play Games
更多相關文章
  • 一、前言: 安卓(Android):是一種基於Linux的自由及開放源代碼的操作系統,主要用在移動設備上,如手機、平板電腦。其他的設備也有使用安卓操作系統,比如:電視機,游戲機、數位相機等等。 二、具體: 1、首先需要有開發安卓的環境,安卓SDK。在此本人提供Android4.4的版本下載鏈接:ht ...
  • 前言 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 "HTML快速入門(一)" 學習 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質瞭解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝 文章第一版出自簡書,如果 ...
  • Android Weekly閱讀筆記, Issue #231, 本期內容包括: MVP中的View做成passive響應式的, 返回Observable; Android Studio使用技巧; `BottomNavigationView`的使用; App tracking; Kotlin; 用Ko... ...
  • 開發環境: macOS 10.12.1 Xcode 8.1 Qt 5.8 iPhone 6S+iOS 10.1.1 源代碼: 我在 Qt 程式里指定了資料庫的名稱來創建資料庫,在 Win10、Android、macOS 下正常運行,但是在蘋果手機上報錯。 QSqlDatabase db; db.se ...
  • 轉載請標明出處:http://www.cnblogs.com/zhaoyanjun/p/6074887.html1 本文出自 "【趙彥軍的博客】" 反射機制是什麼 反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲 ...
  • - (BOOL) isBlankString:(NSString *)string { if (string == nil || string == NULL) { return YES; } if ([string isKindOfClass:[NSNull class]]) { return Y ...
  • 開源項目 wechat-weapp-gank - 微信小程式版Gank客戶端 wechat-dribbble - 微信小程式-Dribbble wechatApp-demo - 微信小程式 DEMO weapp-ide-crack - 微信小應用資源破解 API - API 文檔 weapp-qui ...
  • 在eclipse中導入android項目,項目正常沒有任何錯誤,但是運行時候會報錯,(clean什麼的都沒用了。。。。。)如圖: 百度大神大多說是jdk的問題,解決: 右鍵項目—Properties如下圖: 我的原來是1.8,換成1.7點擊Apply—ok。解決。 備忘,希望給大家帶來幫助,有錯誤請 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...