上手开发Android需要掌握什么呐

一、Intent传值

在这里,我们从MainActivity中向EditTextActivity中传值,并取回用户在文本框中输入的内容。

//MainActivity中的方法
btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //MainActivity中向EditTextActivity中传值
                Intent intent = new Intent(MainActivity.this, EditTextActivity.class);
                intent.putExtra("name", "value");
                //启动活动,获取结果
                startActivityForResult(intent, 0);
            }
        });

//第二个方法
//接收startActivityForResult的结果
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode,resultCode,data)
        String edit = data.getStringExtra("input")
    }
//在EditTextActivity中接收
@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_HOME) {
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
            Intent intent = new Intent();
            autoSetMessage(intent);
            //按下返回键,将页面的文本获取,并返回
//            intent.putExtra("内容", editText.getText().toString());
            setResult(RESULT_OK, intent);
            finish(); //关闭活动
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

二、数据库—Database类和CRUD

首先用代码介绍一下Database的类
public class NoteDatabase extends SQLiteOpenHelper {
    //设置常量,通过设置属性名,方便后期项目管理,对其识别
    public static final String TABLE_NAME = "notes";
    //content属性表示内容
    public static final String CONTENT = "content";
    //id属性用于定位数据,可在数据库中设置AUTOINCREMENT实现自增长
    public static final String ID = "_id";
    public static final String TIME = "time";
    public static final String MODE = "mode";

    public NoteDatabase(Context context) {
        super(context, "notes", null, 1);
    }

    //创建数据库
    //实际上就是写SQL,创建表
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE_NAME + "(" + ID
                + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                + CONTENT + " TEXT NOT NULL, "
                + TIME + " TEXT NOT NULL, "
                + MODE + " INTEGER DEFAULT 1)");

    }
}
CRUD类
public class CRUD {
    SQLiteOpenHelper dbHandler;  //数据库处理器
    SQLiteDatabase db; //定义数据库

    //取出数据库的数据
    private static final String[] columns = {
            NoteDatabase.ID,
            NoteDatabase.CONTENT,
            NoteDatabase.TIME,
            NoteDatabase.MODE
    };

    //构造方法
    public CRUD(Context context) {
        //实例化SQLiteOpenHelper
        dbHandler = new NoteDatabase(context);
    }

    //对数据库进行写入功能
    public void open() {
        db = dbHandler.getWritableDatabase();
    }

    //关闭数据库
    public void close() {
        dbHandler.close();
    }

    //添加数据加入到database里面
    public Note addNote(Note note) {
        //添加一个笔记到数据库
        //专门处理数据的一个类,相当于一个内容值
        ContentValues contentValues = new ContentValues();
        contentValues.put(NoteDatabase.CONTENT, note.getContent());
        contentValues.put(NoteDatabase.TIME, note.getTime());
        contentValues.put(NoteDatabase.MODE, note.getTog());
        long insertId = db.insert(NoteDatabase.TABLE_NAME, null, contentValues);
        note.setId(insertId);
        return note;
    }

    //通过id获取数据
    public Note getNote(long id) {
        Cursor cursor = db.query(NoteDatabase.TABLE_NAME, columns, NoteDatabase.ID + "=?", new String[]{String.valueOf(id)}, null, null, null);
        if (cursor != null) cursor.moveToFirst();
        Note note = new Note(cursor.getString(1), cursor.getString(2), cursor.getInt(3));
        return note;
    }

    //通过id获取所有数据
    public List<Note> getAllNotes() {
        Cursor cursor = db.query(NoteDatabase.TABLE_NAME, columns, null, null, null, null, null);
        List<Note> list = new ArrayList<>();
        Note note = null;
        if (cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                note = new Note();
                note.setId(cursor.getLong(cursor.getColumnIndex(NoteDatabase.ID)));
                note.setContent(cursor.getString(cursor.getColumnIndex(NoteDatabase.CONTENT)));
                note.setTime(cursor.getString(cursor.getColumnIndex(NoteDatabase.TIME)));
                note.setTog(cursor.getInt(cursor.getColumnIndex(NoteDatabase.MODE)));
                list.add(note);
            }
        }
        return list;
    }

    //修改数据
    public int updateNote(Note note) {
        ContentValues values = new ContentValues();
        values.put(NoteDatabase.CONTENT, note.getContent());
        values.put(NoteDatabase.TIME, note.getTime());
        values.put(NoteDatabase.MODE, note.getTog());
        return db.update(NoteDatabase.TABLE_NAME, values,
                NoteDatabase.ID + "=?", new String[]{String.valueOf(note.getId())});
    }

    //删除数据
    public void removeNote(Note note) {
        db.delete(NoteDatabase.TABLE_NAME, NoteDatabase.ID + "=" + note.getId(), null);
    }

}

三、监听事件和基于事件回调的事件处理机制(捞干的说)

监听事件处理机制

首先我们需要了解监听的三要素:

⭐️Event Source事件源

⭐️Event事件

⭐️Event Listener事件监听器

下面我们用一个例子展示什么是监听器

btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG,"点击了事件");
                //这里补充说明一下Log.d就是在debug那里打印,有很多朋友找不到日志打哪里去了
            }
        });
实现监听的方法

ps:由于考虑文章的延展性,网上这些资料也很多,就不在这里写代码了

1.通过内部类实现

2.通过匿名内部类实现

3.通过事件源所在类实现

4.通过外部类实现(就是在外面建一个java类)

5.布局中的onClick属性(就是在布局xml文件中设置onClick(),记得绑定public方法)

基于回调的事件处理机制

重点:1.回调机制与监听机制的区别. 2.基于回调的事件传播


研究背景:想象一下,目前我们在Activity中绑定了一个控件,然后点击这个控件,我们触发回调。


此时,回调的顺序是:先从控件本身回调,然后,继续执行Activity回调


思考:为什么点击控件会,触发两次回调,回调为什么会传播


观察代码:发现:在回调函数事件方法最后,我们都使用了return false。


当将Activity中的return false修改为return true,此时,将不处罚Activity的回调事件

因为,才是其被消费掉了,不会回调(官话叫,该组件已经对事件进行处理,不用调用其他组件的分发方法了)


结论:事件方法最后如果return false,事件会继续传播,且事件是由内向外传播的(官话叫,该组件不能对事件进行处理,需要按照规则继续分发事件)

事件方法最后如果return true,就代表在本层消费完毕,不会继续传播(官话叫,该组件已经对事件进行处理,不用调用其他组件的分发方法了)

监听执行的顺序,优于回调先执行
研究这个监听和回调有什么用?

监听和回调可以在开发中有效的代替组件之间的传值问题。

例:比如,3个组件之间的传值,组件A、B、C

A是一个Activity,B是一个Fragment依赖于A,C也是一个Fragment依赖于B

此时,如果B直接向C传值,使用bundle方法,可能消耗更多资源。

在这里,我们就可以在B中设置回调方法传值给A,设置监听,通过监听数据的变化,将值传递给C。

emmm,我给你拉出来一个,给你们看看

Fragment-动态添加碎片
private void replaceFragment(Fragment fragment){
    FragmentManager fragmentManager = getSupportFragmentMannager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.right_layout,fragment);
    transaction.addToBackStack(null); //补充:接收一个名字用于描述返回栈的状态(就是点back程序不会退出,而是回到上一个fragment)
    transaction.commit();
}
//总结:
//1.创建待添加碎片,就是new一个fragment
//2.获取FragmentManager,可以直接在activity中getSupportFragmentMannager()调取
//3.开启一个事务,通过调用beginTransaction()方法开启
//4.向容器内添加或替换碎片,一般用replace()方法,其中需要传入容器id和待添加的碎片实例
//5.提交事务,调用commit()

他就是要一直replace,替换替换,传值很麻烦,如果部替换,值传过不去,生命周期只能走一次。

四、ListView

思路:ListView顾名思义,一个列表罢了。

做一个ListView大致就是,先在布局中添加一个ListView,作为容器。

然后把要在列表中重复显示的布局内容写出来。

接下来,想让列表内容,添加到ListView布局中,就需要创建一个适配器(Adapter),去管理ListView的内容(这就是适配器的内容之一啦).

然后数据的话,得有一个实体类(entity)。

最后,在Activity或者Fragment文件把他加载出来就行啦。

RecyclerView

这个比ListView功能强大一点。

这个可以支持横向列表和瀑布流布局。

开发一般用这个多一点吧,学完ListView看这个就行,他俩差不多。

五、网络

WebView

作用:

1.加载URL(网络或者本地assets文件夹下的html文件)

2.加载html代码

3.Native和javaScript相互调用

WebView加载URL
WebView加载网络URL

方法:webview.loadUrl(“http://www.baidu.com”);

WebView加载assets下的html文件

方法:webview.loadUrl(“file://android_asset/test.html”);

WebView加载html代码

方法:webview.loadwData();

webview.loadDataWithBaseURL();

网页的前进和后退

⭐️webview.canGoBack()

⭐️webview.goBack()

⭐️webview.canGoForward()

⭐️webview.goForward()

⭐️webview.canGoBackOrForward(int steps)

[注意]:按下返回键,默认是退出当前Activity,如果希望是WebView内页面后退

@Override
public boolean onKeyDown(int keyCode,KeyEvent event){
    if((keyCode == KeyEvent.KEYCODE_BACE) && webView.canGoBack()){
        webView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode,event)
}
//这个代码只能写在Activity里面,不能写在fragment里面,如果想在Fragment里面做,去网上搜,我看到过
WebView实例代码
public class EmmmmFragment extends BaseFragment {

    @BindView(R.id.web_V)
    WebView webV;
    Unbinder unbinder;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_working_emmmm, container, false);
        unbinder = ButterKnife.bind(this, view);
        //让他默认可以加载js
        webV.getSettings().setJavaScriptEnabled(true);
        //让他可以跳转页面
        webV.setWebViewClient(new MyWebViewClient());
        webV.setWebChromeClient(new MyWebChromeClient());
        //这里难搞啊,我看的视频是https://www.m.baidu.com这样写的,但是我这样写报错,于是就下面这样了
        webV.loadUrl("https://www.baidu.com");
        return view;
    }

    class MyWebViewClient extends WebViewClient{
        @Override
        public boolean shouldOverrideUrlLoading(WebView webV, WebResourceRequest request){
            webCalender.loadUrl(request.getUrl().toString());
            return super.shouldOverrideUrlLoading(webCalender,request);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            Log.d("webView","onPageFinished...");
        }
    }

    class MyWebChromeClient extends WebChromeClient{
        @Override
        public void onProgressChanged(WebView webV, int newProgress) {
            super.onProgressChanged(webCalender, newProgress);
        }

        @Override
        public void onReceivedTitle(WebView webCalender, String title) {
            super.onReceivedTitle(webCalender, title);
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }
}
网络请求
HttpURLConnection
URL url = new UPL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置请求类型
connection.setRequestMethod("GET");  //发送GET请求   GET/POST
//设置请求超时
connection.setConnectTimeout(8000);//时间毫秒值
connection.setReadTimeout(8000);
//获取服务器返回的输入流
InputStream in = connection.getInputStream();
//关闭HTTP
connection.disconnect();
//读取返回流的值
reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
While((line = reader.readLine()) !==null ){
    response.append(line);
}
showResponse(response.toString());

看完这个然后可以学一下OkHttp,学完这个就可以学习比较流行的网络请求框架啦,然后就可以用了,入门新手的话,应该不至于让你做这个吧,做的话网上很多例子,查查就差不多,我感觉,应该写不出一朵花。

六、认识一些项目文件

一般都是做着做着就都知道了,也没必要太系统的学一遍

AndroidMainfest.xml文件

简述:1.程序中定义的所有四大组件,都需要在这个文件里注册

2.给应用程序添加权限声明

其中:

<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
这两行代码所在Activity,表示此Activity是主活动,点开本程序的入口
build.gradle文件
build.gradle(Project)
buildscript {
    repositories {
        jcenter()    //代码托管仓库
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.2"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
        //声明gradle插件
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        jcenter()
    }
}
build.gradle(Module)
plugins {
    id 'com.android.application'  //这是一个应用程序模块
    id 'com.android.library'  //这是一个库模块
}

android {
    compileSdk 31  //指定项目的编译版本

    defaultConfig {
        applicationId "com.co.test"  //指定项目包名
        minSdk 26  //指定项目最低兼容Android系统版本
        targetSdk 31  //运行时权限
        versionCode 1  //项目版本号
        versionName "1.0"  //项目版本名
    }

    buildTypes {  //用于指定安装文件的相关配置
        release {  //正式
            minifyEnabled false  //是否对项目代码进行混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  //指定混淆时使用的规则文件
        }
        debug {  //测试
            minifyEnabled false
        }
    }

dependencies {  //指定项目所有的依赖关系  1.本地依赖 2.库依赖 3.远程依赖
      //需要啥用啥就是了。。。
}

END 详细总结

作者也是一个刚入门的小白- -

也在做一些学习的总结,一些详细的代码和做法,在下面这两篇文章有喔,还有一些经验