Android开发学习------java文件的解读

前面完成了对项目结构和AndroidManifest.xml文件的分析,接下来就是刚创成项目时怎么看也看不懂的java文件了,这个项目模板生成了三个.java文件,通过运行后的比较,应该是三个不同的页面,首先从主活动页面------MainActivity.java开始~

-------------------------------------------------华丽的分割线------------------------------------------------

先附上个人初建项目的MainActivity.java的详细代码:

package com.example.firstapp;

import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.firstapp.databinding.ActivityMainBinding;

import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    private AppBarConfiguration appBarConfiguration;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setSupportActionBar(binding.toolbar);

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

        binding.fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        return NavigationUI.navigateUp(navController, appBarConfiguration)
                || super.onSupportNavigateUp();
    }
}

有点多,就一个个方法来解决吧-_-

protected void onCreate(Bundle savedInstanceState)

代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setSupportActionBar(binding.toolbar);

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

        binding.fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }
  • 首先最开始的@Override不必多说,重写的意思,表示重写了父类函数
  • 其次,可以发现onCreate函数的参数为Bundle类型的参数saveInstanceState,Bundle类型的数据与Map类型的数据相似,都是以键值对的形式存储数据,saveInstanceState这一参数便用来保存Activity的状态。
  • super.onCreate(saveInstanceState)主要是加载一些组件,如果没有这一句,会出现因为子类onCreate方法功能不全而导致的加载错误
  • binding是在MainActivity类中创建的私有变量,注意到它的类型是ActivityMainBinding,我曾尝试在文件中找这个字段的出现,但把我难住了,后来发现它是Android开发的过程中运用视图绑定时自动生成的类,关于视图绑定的详细介绍可以参考官方文档->视图绑定的详细介绍<-这里只根据官方文档做简单的介绍:

通过视图绑定功能,我们可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定后,系统会为该模块中的每个xml布局文件生成一个绑定类,其命名格式为:将xml文件的名称转换为驼峰式大小写,并在末尾添加"Binding"一词。如示例项目的layout目录下有一个activity_main.xml文件:

 在build.gradle文件中也对视图绑定进行了启用:

系统便自动生成了名为ActivityMainBinding的绑定类,且每个绑定类均包含一个getRoot()方法,用于为相应布局文件的根视图提供直接引用,即返回对应的根视图。

那么如何在Activity中使用视图绑定呢?

  1. 首先,调用父类的onCreate()方法必不可少;
  2. 其次,调用生成的绑定类(比如这里的ActivityMainBinding)中包含的静态inflate()方法(参数为getLayoutInflater(),即获得布局inflater)创建该绑定类的实例以供Activity使用;
  3. 之后,通过调用getRoot()方法获取对根视图的引用;
  4. 最后,将根视图传递到setContentView(),使之成为屏幕上的活动视图。

这一过程与javafx中通过fxml加载项目的ui设计很类似。

之后我们就可以使用该绑定类的实例来引用任何视图,如示例代码中的setSupportActionBar(binding.toolbar)引用了实例binding的菜单视图来设置菜单,

->?<-binding.toolbar来自哪里?

A:MainActivity.java对应的xml文件中:

 设置的android:id="@+id/toolbar"就是它的源头~

  • 接下来的三行代码又是新的一个小板块: 

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

首先,NavController字面意思是导航控制器,它主要负责操作Navigation框架下的Fragment的跳转与退出、监听信息等,也可以运用与Activity。总之,NavController可以帮助我们实现页面的跳转

->语句

NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);

的作用是获取NavController的实例,其中"R.id.nav_host_fragment_content_main"字段是Activity布局里fragment控件的id(在该示例项目中是content_main.xml文件中的内容)

->语句

appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();

用到了AppBarConfiguration这一对象,它是NavigationUI用来管理应用程序显示区域左上角的”导航“按钮(通常是”返回“操作)的行为。且在默认情况下,当用户位于导航图的顶级目标位置时,导航按钮将被隐藏,在任何其他目标位置显示为”向上“按钮。最典型的例子就是左上角的返回图标(按钮),在首页不出现,而在其他页面会出现,使用户能够返回页面。

而要将导航图的其实目的地当作唯一的顶级目的地,我们可以创建一个AppBarConfiguration对象并传入相应的导航图,即上面所示语句。

->语句

NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

用到了setupActionBarWithNavController方法,它能使默认操作栏包含导航支持,可以认为是使页面的”导航“按钮生效的方法。

  • 接下来的setOnclickListener()是点击事件的监听方法,我们传入了一个new View.OnClickListener(){}参数,同时新建了一个对象。其实在写到这一步时,编译器会自动给我们补充上对onClick(View view)方法的重写模板,要求我们对该方法重写,为什么呢?查阅资料可以发现,OnClickListener其实是一个接口,我们新创建了一个接口对象,就要实现它的方法。而我们实现了这个方法之后,它并没有在我们的Activity部分调用却生效了,这就是回调,我们实现了它,它却在别的地方被调用(一般是在View中)。具体如下:

这里的setOnClickListener方法前面有binging.fab.,其实是该java文件对应的xml文件(在本示例中是activity_main.xml)已经定义了的:

"fab"其实就是id值的内容,与前面得"binding.toolbar"来历相同 ,同时注意到上图中的标签末尾是"FloatingActionButton",其实就是一种按钮,表明我们绑定的视图控件会显示成为一个按钮,而关于重写得onClick方法中的代码,则是对按钮点击操作的具体实现。

  • 那么新出现的Snackbar以及它那看似复杂的参数列表又是什么呢?

其实,Snackbar是Android开发库中的一个控件,可以快速在屏幕底部弹出信息。使用它需要导入com.android.support:design库(这里应该是创建项目时系统会自动导入的),它会显示在屏幕的所有其他元素之上,也就是显示在屏幕的最顶层(由此可以想到用它做桌面歌词显示),但同一时间只能显示一个snackbar。

使用Snackbar就要用到上面我们从未遇到过又看上去比较复杂的方法:

Snackbar.make(View view,CharSequence message,int duration)
        .setAction(CharSequence action_text,OnClickListener click_listener)
        .show();

其中,make方法有三个参数,分别表示空间容器view,显示文字,显示时间(有三种类型LENGTH_SHORT,LENGTH_LONG,LENGTH_INDEFINITE,分别表示短时、长时、不限时),用来生成Snackbar;

setAction方法可设置Snackbar的右侧按钮,增加交互事件,而如果不适用该方法,就只显示左侧的信息(该方法的第二个参数还可以新建一个接口对象并实现它的onClick方法实现点击按钮后的信息显示);

show()方法很好理解,就是显示出来。

public boolean onCreateOptionsMenu(Menu menu)

代码:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

Android一个有三种形式的菜单:

  • 选项菜单(optionsMenu)
  • 上下文菜单(ContextMenu)
  • 子菜单(subMenu)

其中选项菜单最为常用,在点击相关按钮后,会在对应的活动(Activity)底部显示出来

这里的onCreateOptionsMenu(Menu menu)方法是管理菜单的要用到的方法之一,它用于初始化菜单,其中的menu参数就是将要显示出来的Menu实例。若返回值为true,则显示该菜单,否则不显示。其中getMenuInflater()方法返回一个MenuInflater,再使用它的inflate方法把布局文件中定义的菜单加载给其参数列表第二个参数所对应的menu对象。

参数R.menu.menu_main对应的是res资源包下menu目录的menu_main.xml文件:

 

public boolean onOptionsItemSelected(MenuItem item)

代码:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

这一块是菜单项监听方法,菜单被点击时会被调用,通过获取当前元素id并判断是否与菜单控件id相等来进行相应的操作

public boolean onSupportNavigateUp()

代码:

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        return NavigationUI.navigateUp(navController, appBarConfiguration)
                || super.onSupportNavigateUp();
    }
}

这一块的作用是通过重写onSupportNavigateUp方法来实现程序的后退功能,同时将navController和appBarConfiguration传递到Navigation.navigateUp,实现导航栏对于fragment的切换,即若有两个以上的fragment,点击返回即可进行页面的跳转。

详细实现方法中第一行即之前遇到过的获取NavController(导航控制器)的实例,之后返回一个boolean值

-------------------------------------------------华丽的分割线------------------------------------------------

对于MainActivity.java的分析暂时到这里告一段落,虽然码了这么多,但是不代表自己已经搞懂了,毕竟网上对于一些知识的解答少之又少,甚至只能自己推测,因此可能在将来的某一天会发现这其中的错误......

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值