这可能是最详细的monkeyc开发手册!篇幅较长全文15000字,
建议根据目录选择性观看,可以收藏开发时查找(每个功能点都有示例)
大标题后括号中有标注希望对你有所帮助!!!
程序的类型
Connect IQ 系统中有五种应用类型:
- 表盘- 这是 Garmin 可穿戴设备的主屏幕。它们可以是简单的钟表,也可以是包含数十种健康和健身统计数据的复杂数据屏幕。
- 数据字段- 数据字段是 Garmin 活动体验的插件。它们允许计算新指标或允许将新数据带入锻炼。
- 小部件- 小部件是可以从主屏幕启动的微型应用程序。它们旨在提供一目了然的信息访问。
- 设备应用程序- 设备应用程序是最强大的应用程序类型,并提供对系统的完全访问权限。
- 音频内容提供商- 音频内容提供商是音乐可穿戴设备上媒体播放器的插件,它们在媒体和第三方内容服务之间架起了桥梁。
API 和应用权限
应用类型定义了应用的用户上下文。例如,表盘由于在低功耗模式下运行,因此受到许多限制。为了强制执行这些限制,Connect IQ 虚拟机将根据您的应用类型限制可用的 API。
*需要应用程序权限
** API 级别 5.0.0 中引入数据字段中的通信支持您的应用类型所请求的 Toybox 模块超出此列表范围将导致“*未找到符号”*错误。
开发注意事项
1、可访问模块。
- 出于对电池寿命的担忧,表盘对系统中 API 的访问最少。它们可以访问
图形、位图、字体、当前活动跟踪器状态、当前电池状态和用户的活动资料
。它们无法访问指南针、GPS 或其他传感器
。
2、自定义字体。
- 如果您使用
自定义字体
来显示数字,请使用过滤器选项仅加载关键字形
。这将节省内存,您可以将其用于其他图形
3、表盘睡眠。
- 表盘大部分时间处于“睡眠模式”。在此模式下,执行仅限于每分钟更新一次,并且不能使用计时器或动画。当用户抬起手表查看时,表盘将退出睡眠模式。发生这种情况时,将
WatchFace.onExitSleep()
调用该方法,更新将增加到每秒一次,并且允许使用计时器和动画,直到WatchFace.onEnterSleep()
调用该方法为止。
4、表盘委托
自 API 级别 2.3.0 起
为表盘提供WatchUi.WatchFaceDelegate
系统输入。该委托应作为返回数组的第二个元素返回,AppBase.getInitialView()
类似于其他应用程序类型的输入委托。此委托目前仅用于报告支持每秒更新的表盘的电量预算违规。如果在一分钟内超出执行预算,WatchFaceDelegate.onPowerBudgetExceeded()
则会调用回调,提供有关表盘执行时间以及超出限制的信息。
5、数据字段和简单数据字段
数据字段的基类是WatchUi.DataField
。此类扩展了WatchUi.View
,并且在许多方面与其他 View 对象的行为类似。View.onUpdate()
每次数据字段需要更新时,都会进行方法调用。
在 Garmin 活动中,用户控制数据页面布局;具体来说,是显示一个、两个、三个还是更多字段。Connect IQ 数据字段必须处理所有这些布局中的显示,开发人员可以使用模拟器在设备支持的所有布局中测试他们的字段。
许多开发人员只想显示单个值,而不想处理绘制数据字段的所有复杂性。在这些情况下,他们可以使用对象WatchUi.SimpleDataField
。简单的数据字段可以处理多种尺寸的字段绘制,并且只需要开发人员实现一种DataField.compute()
方法。该compute()
方法传递一个Activity.Info
对象,其中包含所有当前锻炼信息。
尽可能使用SimpleDataField
,以确保您数据字段具有其他 Garmin 数据字段的原生外观和感觉。Connect IQ 将尝试确保您的数据以最佳字体和布局显示。
以下是“Beers Earned”数据字段的示例,它显示您在锻炼期间“赢得”了多少杯啤酒:
Monkey C编程语言
monkeyc
是 Garmin 的 Connect IQ 平台上使用的一种编程语言。它是 Garmin 特别为其可穿戴设备开发的,这些设备包括智能手表和其他健康跟踪器。monkeyc
是一种高层次、面向对象的语言,设计上与 Java 和 JavaScript 类似,这使得熟悉这些语言的开发者能够较快地上手。
monkeyc
的特性(概念)
- 语法: 与 Java 类似,
monkeyc
使用面向对象的编程结构,包括类、继承和接口。 - 跨平台: 适用于所有支持 Connect IQ 的 Garmin 设备。
- 轻量化: 由于设备资源有限,
monkeyc
被设计为一种轻量级的语言,专门用于开发高效的小型应用程序。 - 专用 API: 提供了丰富的 API,帮助开发者访问设备的传感器数据、UI 元素、文件系统等。
总的来说:monkeyc是开发佳明应用的语言,以.mc结尾。
示例(概念)
using Toybox.Application as App;
using Toybox.System;
class MyProjectApp extends App.AppBase {
// onStart() is called on application start up
function onStart(state) {
}
// onStop() is called when your application is exiting
function onStop(state) {
}
// Return the initial view of your application here
function getInitialView() {
return [ new MyProjectView() ];
}
}
顶部是 using 语句,它类似于 C++ 的
using
语句,或import
Java™、Ruby 或 Python™ 中的 。using
语句在词汇上将模块带入我们的名称空间。 在子句之后using
,我们可以通过其缩写名称(在本例中为 )来引用模块System
。Toybox
是 Monkey C 系统模块的根模块;所有酷炫的操作都保存在那里。
要将值打印到调试控制台,请使用:
System.println( "Hello Monkey C!" );
System
指的是Toybox.System
我们用该using
语句导入的模块。与 Java 命名空间不同,Monkey C 中的模块是静态对象,可以包含函数、类和变量。Javaprintln()
程序员应该很熟悉该函数 - 它打印一个字符串并自动添加一个新行。该System
模块有许多有用的功能:
print
并将println
输出发送到控制台getTimer
返回当前毫秒计时器。该值是一个 32 位整数,表示系统已运行的毫秒数。该值可用于计时,但允许翻转。getSystemStats
提供运行时系统的统计数据exit
将终止你的申请error
将退出应用程序并记录错误消息
与java比较(概念)
与 Java 一样,Monkey C 编译为虚拟机解释的字节码。此外,与 Java 一样,所有对象都分配在堆上,虚拟机会清理内存(Java 通过垃圾收集,Monkey C 通过引用计数)。与 Java 不同,Monkey C 没有原始类型 - 整数、浮点数和字符都是对象。这意味着原始类型
可以像其他对象一样拥有方法。
Java 是一种静态类型语言,而 Monkey C 是鸭子类型。在 Java 中,开发人员必须声明函数所有参数的类型
,并声明返回值的类型。Java 编译器会在编译时检查这些内容,以确保类型安全。鸭子类型的概念是“如果它走路像鸭子,叫声像鸭子,那么它一定是鸭子” [1]。例如:
function add( a, b ) {
return a + b;
}
// Monkey C 编译器不验证类型安全性,如果函数错误处理方法,则会导致运行时错误。
function thisFunctionUsesAdd() {
var a = add( 1, 3 ); // Return 4
var b = add( "Hello ", "World" ); // Returns "Hello World"
}
对象、模块和内存(注意事项)
对象使用关键字创建class
。类允许将数据和操作绑定到对象上。在 Monkey C 中,可以在类中定义变量
、函数
和其他类
。
构造函数
当使用该关键字实例化一个对象时new
,会分配内存并initialize
调用该方法:
class Circle{
protected var mRadius;
public function initialize( aRadius ) {
mRadius = aRadius;
}
}
function createCircle() {
var c = new Circle( 1.5 );
}
在方法中你可以用self
或者me
代替java中的this关键字引用当前实例。
class A
{
public var x;
public var y;
public function initialize() {
me.x = "Hello"; // Set current instance x variable
self.y = "Hello"; // Set current instance y variable
}
}
继承
Monkey C 使用extends
关键字来支持类继承:
import Toybox.System;
class A
{
function print() {
System.print( "Hello!" );
}
}
class B extends A
{
}
function usageSample() {
var inst = new B();
inst.print(); // Prints "Hello!"
}
你可以增强方法:
import Toybox.System;
class A
{
function print() {
System.print( "Hello!" );
}
}
class B extends A
{
function print() {
// Call the super class implementation
A.print();
// Amend the output
System.println( "Hola!" );
}
}
function usageSample() {
var inst = new B();
inst.print(); // Prints "Hello! Hola!"
}
字段访问级别
有三个访问级别—— public
、protected
和private
。
public
是默认值,但也可以明确指定。当public
访问修饰符用于枚举、变量或函数时,这些成员对所有其他类都是可见的。
修饰符private
指定该成员只能在其自己的类中访问。
修饰符protected
指定该成员只能由其自身类或其子类之一访问。 关键字hidden
与 关键字同义protected
。
import Toybox.System;
class Foo
{
public var publicVar;
protected var _protectedVar
private var _privateVar;
public function initialize() {
publicVar = "a";
_protectedVar = "b";
_privateVar = "c";
}
}
class Bar extends Foo {
public function initialize() {
// Initialize the parent
Foo.initialize();
publicVar = "b";
_protectedVar = "c";
// Error - can't access private member
_privateVar = "d";
}
}
function usageSample() {
var v = new Foo();
System.println( v.publicVar );
// Error - cannot access protected member
System.println( v._protectedVar );
// Error - cannot access private member
System.println( v._privateVar );
}
多态
大多数面向对象语言都支持多态函数的概念,即一个函数可以根据输入参数的数量和类型有多个定义。部分由于其鸭子类型的特性,Monkey C 不支持这种运行时多态性。
因为函数参数是鸭子类型,所以可以使用instanceof
运算符实现某种程度的多态性:
import Toybox.Lang;
function aPolymorphicFunction(a) {
switch(a) {
case instanceof String:
return doTheStringVersion(a);
case instanceof Number:
case instanceof Long:
return doTheNumericVersion(a);
default:
throw new UnexpectedTypeException();
}
}
强引用和弱引用
Monkey C 是引用计数的,这意味着当引用该内存的对象数量减少到零时,运行时系统将释放内存。引用计数允许内存非常快速地变为可用,这在低内存环境中非常重要。引用计数的弱点是循环引用。当引用链中形成一个循环时,就会发生循环引用。例如,假设对象 C 引用对象 A,对象 A 引用对象 B,对象B 引用对象 A。
要创建弱引用,请使用weak()
方法。Weak 是 Monkey C 中的一种方法Lang.Object
,可供所有 Monkey C 对象使用。
// I would make a "Hans and Franz" reference but I
// think certain advertising has made them uncool.
var weakRef = obj.weak()
如果你调用的是weak
其中一种不可变类型(Number
,Float
,Char
,Long
,Double
)String
,那么它将返回对象本身。否则它将返回一个WeakReference
实例。
//! A weak reference is a loosely bound reference to
//! another object. If all strong references have been
//! freed, the get() method will return null.
//! This allows the developer to avoid circular references.
//! @since 1.2.0
class WeakReference
{
//! Return if the reference is still alive.
//! @return true if object is still alive, false otherwise.
//! When you are dead I will be STILL ALIVE
//! I feel fantastic and I am STILL ALIVE
function stillAlive();
//! Get the object referenced.
//! @return Object referenced, or null if object is no
//! longer alive.
function get();
}
您可以使用该stillAlive
方法检查引用是否已被清除。用于get
创建对该对象的强引用。仅在需要的范围内保留强引用!
// This is a triumph...
if( weakRef.stillAlive() ) {
var strongRef = weakRef.get();
strongRef.doTheThing();
}
导入和使用语句
您可以使用关键字将模块带入您的作用域级别import
。使用时,import
它会将模块后缀和模块中的所有类带入类型命名空间。这样就可以访问模块中的类而无需模块后缀