Cordova源码解析(2)_CordovaActivity分析

版权声明:本博客主要记录学习笔记和遇到的一些问题解决方案,转载请注明出处! https://blog.csdn.net/u010982507/article/details/86382103

上一篇讲述了cordova工程的创建,并成功运行起来,那cordova是如何加载html页面的,本文就来详细分析一下。

MainActivity 分析

App的入口是MainActivity,打开MainActivity可以看到是继承于CordovaActivity,在onCreate中的loadUrl方法和launchUrl属性都是从CordovaActivity中继承来的,所以CordovaActivitycordova的入口。

public class MainActivity extends CordovaActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // enable Cordova apps to be started in the background
        // 获取外部传来的数据
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }
        // 加载html
        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
    }
}

CordovaActivity 分析

一、OnCreate方法
进入CordovaActivity 类,可以看到CordovaActivity继承于Activity,这个类主要是完成对cordova的基本配置和初始化工作,根据Activity的生命周期,先从OnCreate开始分析:
1、在OnCreate中第一个方法是loadConfig方法,如下所示:

protected void loadConfig() {
    ConfigXmlParser parser = new ConfigXmlParser();
    parser.parse(this);
    preferences = parser.getPreferences();
    preferences.setPreferencesBundle(getIntent().getExtras());
    launchUrl = parser.getLaunchUrl();
    pluginEntries = parser.getPluginEntries();
    Config.parser = parser;
}

loadConfig方法首先初始化了ConfigXmlParser类,而ConfigXmlParser的主要属性和方法有:

  • CordovaPreferences类:负责解析config.xml<preference name="loglevel" value="DEBUG" />节点;
  • launchUrl属性值:默认是file:///android_asset/www/index.html
  • setStartUrl方法:判断config.xml中是否配置了<content src="index.html" />;
  • parse方法:解析了res/xml目录下的config.xml文件

2、初始化完配置,接着初始化日志,设置日志级别。

String logLevel = preferences.getString("loglevel", "ERROR");
LOG.setLogLevel(logLevel);

3、再往下就是配置窗口是否全屏,是否有标题。

if (!preferences.getBoolean("ShowTitle", false)) {
    getWindow().requestFeature(Window.FEATURE_NO_TITLE);
}
if (preferences.getBoolean("SetFullscreen", false)) {
    LOG.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
    preferences.set("Fullscreen", true);
}
if (preferences.getBoolean("Fullscreen", false)) {
    // NOTE: use the FullscreenNotImmersive configuration key to set the activity in a REAL full screen
    // (as was the case in previous cordova versions)
    if (!preferences.getBoolean("FullscreenNotImmersive", false)) {
        immersiveMode = true;
    } else {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
} else {
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
}

二、loadUrl方法
loadUrl方法是在MainActivity中调用的,这个方法的实现如下所示:

public void loadUrl(String url) {
    if (appView == null) {
        init();
    }
    // If keepRunning
    this.keepRunning = preferences.getBoolean("KeepRunning", true);
    appView.loadUrlIntoView(url, true);
}

这个方法首先执行了init()方法,在init方法中创建了appView也就是webview实例,执行方法如下:

appView = makeWebView();

而makeWebView()方法里实现了CordovaWebViewImpl实例,顾名思义,这个类是CordovaWebView的实现类,这个类留着以后讲。

protected CordovaWebView makeWebView() {
    return new CordovaWebViewImpl(makeWebViewEngine());
}

protected CordovaWebViewEngine makeWebViewEngine() {
    return CordovaWebViewImpl.createEngine(this, preferences);
}

创建了webview的实例appView,接着就是设置CordovaActivity的布局,执行的方法是createViews(),设置完布局,再往下执行appView的初始化和cordovaInterface的初始化,这些类都在以后讲。
看完了init方法,再往下就是使用webview加载html的url了

appView.loadUrlIntoView(url, true);

三、Activity生命周期方法
CordovaActivity中的关键方法就是上述的那些,当然还有许多方法,不过都是些继承方法,下面列举一下:

  • onPause
  • onNewIntent
  • onResume
  • onStop
  • onStart
  • onDestroy
    这些都是Activity的生命周期方法,在这些方法中,都实现了webview对应的方法,这些方法其实是对插件的处理。如:
@Override
protected void onStart() {
    super.onStart();
    LOG.d(TAG, "Started the activity.");

    if (this.appView == null) {
        return;
    }
    this.appView.handleStart();
}

在CordovaActivity的onStart方法中执行了this.appView.handleStart();方法,而handleStart方法中实现了

@Override
public void handleStart() {
    if (!isInitialized()) {
        return;
    }
    pluginManager.onStart();
}

这些以后在分析CordovaWebViewImpl这个类的时候再详细说明。

四、Activity继承方法
除了生命周期方法,还有

  • startActivityForResult
  • onActivityResult
  • onRequestPermissionsResult
  • onSaveInstanceState
  • onWindowFocusChanged
  • onConfigurationChanged
  • onOptionsItemSelected
  • onPrepareOptionsMenu
  • onCreateOptionsMenu

这些都是Activity的继承方法,大家都很熟悉就不做讲解了。

四、onReceivedError继承方法
下面再讲一个比较重要的方法:错误处理页面。
在CordovaActivity中有个onReceivedError方法,这个方法就是处理当前html页面报错了,会跳转到另一个页面显示错误提示信息,类似于访问网页找不到的时候,显示一个404页面。

public void onReceivedError(final int errorCode, final String description, final String failingUrl) {
     final CordovaActivity me = this;

     // If errorUrl specified, then load it
     final String errorUrl = preferences.getString("errorUrl", null);
     if ((errorUrl != null) && (!failingUrl.equals(errorUrl)) && (appView != null)) {
         // Load URL on UI thread
         me.runOnUiThread(new Runnable() {
             public void run() {
                 me.appView.showWebPage(errorUrl, false, true, null);
             }
         });
     }
     // If not, then display error dialog
     else {
         final boolean exit = !(errorCode == WebViewClient.ERROR_HOST_LOOKUP);
         me.runOnUiThread(new Runnable() {
             public void run() {
                 if (exit) {
                     me.appView.getView().setVisibility(View.GONE);
                     me.displayError("Application Error", description + " (" + failingUrl + ")", "OK", exit);
                 }
             }
         });
     }
 }

这个方法处理逻辑是,判断是否在config.xml页面配置了errorUrl,如果配置了errorUrl,那么就跳转到这个url指向的html页面,如下所示:

me.appView.showWebPage(errorUrl, false, true, null);

如果没配置就隐藏掉webview,并调用displayError方法

me.appView.getView().setVisibility(View.GONE);
me.displayError("Application Error", description + " (" + failingUrl + ")", "OK", exit);

displayError方法的实现很简单,其实就是创建一个AlertDialog来提示信息。

public void displayError(final String title, final String message, final String button, final boolean exit) {
    final CordovaActivity me = this;
    me.runOnUiThread(new Runnable() {
        public void run() {
            try {
                AlertDialog.Builder dlg = new AlertDialog.Builder(me);
                dlg.setMessage(message);
                dlg.setTitle(title);
                dlg.setCancelable(false);
                dlg.setPositiveButton(button,
                        new AlertDialog.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                if (exit) {
                                    finish();
                                }
                            }
                        });
                dlg.create();
                dlg.show();
            } catch (Exception e) {
                finish();
            }
        }
    });
}

到此,CordovaActivity的分析结束,可能还有些细节没分析到,这些就留给大家自己思考吧。

猜你喜欢

转载自blog.csdn.net/u010982507/article/details/86382103