当前位置: 首页 > 编程日记 > 正文

另辟蹊径创建移动应用:iOS和Android代码共享

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

过去几年,移动应用席卷了整个世界,在工作和生活的方方面面改变着我们使用互联网的方式。创建移动应用的各种技术也随之兴起,各种开发流程也 将移动应用视为一等公民,开始考虑适应移动开发的流程。尽管已经让人感觉无处不在,真正的移动应用时代才刚刚开始。我们即将面对新一代的移动设备,如可穿戴设备或组成物联网的各种各样的移动装置。我们将面临全新的用于数据展示和命令接收的用户交互接口。我们也认识到越来越多的公司将真正采取移动优先的战 略。所有的这些都将对我们未来几年设计、开发和测试软件的方式产生巨大影响。

在苹果和安卓的应用商店中有成千上万各种用途的移动应用。iOS设备上的应用通常使用Objective-C工具库创建而成,而安卓设备上的应用则 基于Java语言。在这篇文章中我们将向您展示两种不太常用的使用Java和Xtend构建原生应用的方法,这两种方法能够帮助开发者在两个应用平台上共享代码,从而简化开发工作。

使用Java和RoboVM开发原生iOS应用

将安卓和iOS两个平台同时作为目标平台的移动应用开发者经常面临很多挑战。在比较这两个平台的原生应用开发环境时,例如分别由谷歌和苹果提供的开 发工具链,很容易就能够发现这两者之间有着本质的区别。谷歌所提供的安卓开发环境是基于Eclipse集成开发环境和Java程序设计语言的。而由苹果所 提供的iOS开发环境则是基于Xcode集成开发环境和Objective-C程序设计语言的。

这些平台间的差异导致代码无法重用。而且很少有开发者能够同时精通两个环境。最终就导致几乎每个跨平台的移动应用都需要为各个平台准备单独的开发团队并使用单独的代码库。

RoboVM是一个新的开源项目,旨在不影响开发者和应用用户体验的前提下解决上述问题。RoboVM项目的目标是在iOS设备上使用Java和其 他JVM语言,如Scala,Clojure和Kotlin。与其他类似的工具不同,RoboVM不会对开发者所使用的Java平台特性做任何限制,如反 射机制或文件I/O,并且还允许开发人员重用Java庞大的第三方库生态系统。RoboVM的独特之处还在于开发人员能够通过一个Java到 Objective-C的桥接器访问到完整的原生iOS API。这样,应用程序开发时,就能够用Java语言编写真正的原生用户交互界面并且能够获取到完整的硬件访问权限,同时使用的开发工具也是Java开发 人员所熟悉的Eclipse和Maven等。

使用RoboVM,进行跨平台开发将变得相对容易;同一组Java开发人员就有能力构建两个版本的移动应用程序并且代码库中的相当一部分代码都能够被共享。

如何开始?

RoboVM有多种调用方式,如命令行方式或使用Maven或Gradle,最容易上手的方式应该是使用RoboVM的Eclipse插件。

配置要求

安装RoboVM的Eclipse插件之前,请确保系统满足如下要求:

  • 一台运行Mac OS X 10.9操作系统的Mac电脑。
  • Oracle Java SE 7 JDK。
  • 从Mac应用商店下载的Xcode 5.x集成开发环境。

需要注意的是,必须使用Oracle Java SE 7 JDK运行Eclipse。Eclipse无法正常运行在苹果的Java 6 JVM之上。

安装RoboVM的Eclipse插件

系统满足所有的先决条件之后,安装插件是一项很简单的工作。从Eclipse的Help菜单中打开Eclipse Marketplace,搜索RoboVM并点击Install Now即可。

或者也可以使用如下更新站点。

运行一个简单的iOS应用

接下来我们将创建一个简单的iOS应用。首先创建一个新的项目:File => New => Project......。在列表中选择RoboVM iOS Project向导。

在Project Name,Main Class和App name栏中输入IOSDemo,在App id一栏中输入org.robovm.IOSDemo。其他栏目保持默认值点击Finish。

然后,创建一个新的名为IOSDemo的类文件,省略包名。将下面的代码拷贝粘贴到新创建的文件中,替换Eclipse自动生成的代码。

import org.robovm.apple.coregraphics.*;  import org.robovm.apple.foundation.*;  import org.robovm.apple.uikit.*;    public class IOSDemo extends UIApplicationDelegateAdapter {        private UIWindow window = null     private int clickCount = 0       @Override      public boolean didFinishLaunching(UIApplication application,              NSDictionary launchOptions) {            final UIButton button = UIButton.create(UIButtonType.RoundedRect);          button.setFrame(new CGRect(115.0f, 121.0f, 91.0f, 37.0f));          button.setTitle("Click me!", UIControlState.Normal);            button.addOnTouchUpInsideListener(new UIControl.OnTouchUpInsideListener() {              @Override              public void onTouchUpInside(UIControl control, UIEvent event) {                  button.setTitle("Click #" + (++clickCount), UIControlState.Normal);                    }              });                window = new UIWindow(UIScreen.getMainScreen().getBounds());              window.setBackgroundColor(UIColor.colorLightGray());              window.addSubview(button);              window.makeKeyAndVisible();                return true        }                 public static void main(String[] args) {              NSAutoreleasePool pool = new NSAutoreleasePool();              UIApplication.main(args, null, IOSDemo.class);              pool.close();         } 

最后,右键点击刚刚创建的项目,选择Run As... =>iOS Simulator App (iPhone),在iOS模拟器中启动应用程序。这样,应用程序就运行在一个模拟的iPhone上了。

如果需要在真实的设备上运行应用程序,需要使用Run As... =>iOS Device App选项。需要注意的是,执行这一选项之前,所用到的设备需要进行相应的设置。设置的过程超出了本文的讨论范围。详细信息请参照苹果的官方文档。

创建用于应用商店发布的IPA文件

如果应用商店的发布证书(Distribution Certificate)和应用描述文件(Provisioning Profile)已经准备妥当,创建用于提交到应用商店的IPA软件包只需要在Eclipse中右键点击RoboVM iOS项目,选择RoboVM Tools=>Package for App Store/Ad-Hoc distribution… ,填写对话框中相关信息即可。

完成上述操作后,将会在目标文件夹中生成一个后缀为.IPA的文件。使用Application Loader即可验证生成的IPA文件并将其提交到应用商店中。使用Spotlight可以很方便地定位到Application Loader应用。

从苹果网站上能够找到很多关于如何加入iOS开发者计划及如何创建用于应用商店发布的证书和应用描述文件的资源。

底层实现机制

字节码编译器

RoboVM的核心是它的预编译器。预编译器可以通过命令行或者Maven、Gradle等构建工具或IDE调用。它可以将Java字节码翻译成用 于特定操作系统和CPU型号的机器码。一般来说会翻译成用于iOS系统和ARM处理器的机器码,不过RoboVM也支持将字节码转为运行在x86 CPU(32位)上的Mac OS X和Linux系统的机器码。

这种预编译的方法与Oracle Hotspot之类的传统JVM的工作机制有很大的区别。这些JVM通常会在运行时读取Java字节码,然后以某种方式执行包含在字节码的虚拟机指令。为 了加快这一进程,JVM采用了一种被称为即时编译的技术。简单来说,这个过程会在程序第一次调用某个方法时,将这一方法的虚拟机指令翻译成当前系统所用的 CPU型号对应的机器码。

由于苹果内置于iOS中的技术限制,在iOS应用中使用任何形式的即时编译技术都是不可能的。唯一的替代方案就是使用解释器或像RoboVM中所用 的预编译技术,而解释器这种方式速度很慢并且十分耗电。预编译的过程发生在使用开发者的机器进行编译的时候,在iOS设备上运行时,生成的机器码就能够全 速运行,因此在速度上可以与由Objective-C编译生成的代码媲美,甚至可能会更快一些。

由于RoboVM预编译器消费Java字节码,而不是Java源代码,因此至少在理论上可以用于任何能够编译成字节码的JVM语言。目前已知的 RoboVM预编译器能够正常工作的JVM语言有Scala,Clojure和Kotlin。这种方法的另一个好处是,可在无需任何原始源代码的情况下, 在标准JAR文件中的第三方库上使用RoboVM,这样就可以在应用中使用专有的和闭源的库。

增量编译

即使是非常简单的RoboVM应用,例如IOSDemo应用,在第一次启动时,都需要耗费较长一段时间。RoboVM编译器编译应用的过程是从应用 的main类开始。然后编译main类所用到的所有的类,之后再编译前面的类所用到的所有类,如此循环,直到应用所需的所有类均完成编译为止。在这一过程 中,标准的运行时类,如java.lang.Object和java.lang.String,也包含在编译的范围内。这是一个一次性的过程。 RoboVM会缓存已经编译过的类,只有一个类或与它有直接依赖关系的类已经发生了改变时,才会重新编译这个类。

增量编译和缓存目标文件的好处在于能够减少编译所耗费的时间。在生成的可执行文件中仅包含能够从Main类触及到的类可以降低可执行文件的大小。不 过,在某些情况下(如通过反射机制加载类时),RoboVM编译器无法决定是否应该对某个类进行编译。不过,可以给编译器下达指令,显式地将某个特定的类 或者所有符合某个条件的类包含在编译范围内。

基于安卓的运行时类库

任何的JVM虚拟机都需要运行时类库。这个类库为所有的Java程序提供标准的包和类,如java.lang.Object和 java.lang.String。RoboVM的运行时类库来自于安卓开源项目和已经被移植到RoboVM的非安卓专用的包中。这就意味着如果Java 或JVM代码中只用到了安卓标准包中的类,那么这些代码直接就能够在RoboVM上正常运行。

RoboVM现状

RoboVM目前仍在开发过程中,不过已经可以基本使用。1.0版本预计将在2014年年底之前发布。

在苹果应用商店中已经有至少50个基于RoboVM的应用。已知应用程序的最新列表请参见这里。

目前为止,大概有50%左右的iOS API可用在基于RoboVM的iOS应用中。在RoboVM的Wiki上可以查看到关于这些绑定的当前状态列表。截至现在,RoboVM上已经能够运行由Scala,Clojure和Kotlin所编写的代码。

关于RoboVM的文档,目前仍在完善过程中。在2014年晚些时候,1.0版本发布时,将会有较为完备的文档说明。

RoboVM的应用目前仍无法进行Debug。这一问题也将在今年的晚些时候解决。

限制

RoboVM只能够将已经完成预编译的类加载到应用中。这就意味着在RoboVM应用中,无法在运行时使用自定义的类加载器动态创建字节码并将其加载到应用中。也就是说,RoboVM无法支持运行时创建或修改类的技术。

更多相关信息

  • 关于RoboVM项目的更多信息请参考RoboVM网站。
  • 可以从GitHub上下载到RoboVM源码
  • 关于如何配置测试设备请参考苹果的文档“配置用于开发的iOS设备”。
  • 关于如何提交应用到应用商店,请参考苹果的应用发布指南。

使用Xtend创建安卓应用

Xtend简介

Xtend 1是一种可以编译成可读Java源码的静态类型程序设计语言。这种语言本身是同类设计中的最佳典范,特别是在可 读性和强大的可扩展性方面,不过它也让Java的互操作性问题显而易见。这种语言鼓吹函数式编程风格和多分派、扩展方法、拉姆达表达式及编译期宏等特性。 与其他的Java替代品不同,Xtend本身并不包含庞大的标准库,而只是在标准的JDK上添加了一些扩展方法。Xtend还可以保证避免Java互操作 性问题的出现并且能够提供强大的IDE支持。

为什么安卓上的Java如此难用

Java代码往往十分冗长,特别是在安卓操作系统上。由于Android API的级别很低而且经常出现没有经过充分定义的类型(到处都是int类型)。另外一个烦恼就是无处不在的XML文件的使用和绑定。由于Android上 尚未支持Java 8,我们还不得不仔细阅读无处不在的匿名类。而且不幸的是,Java无法修剪代码以增强可读性,我们只能将代码与多余的符号、类型信息和样板习语 (boilerplate idioms)混杂在一起。

安卓对JVM语言的最低要求

Java语言在安卓上的替代品必须要能够保证不增加任何运行时的系统开销,这就将所有的动态语言排除在外。另外,也不希望出现任何不必要的间接类型 转换。例如,代码中应该只使用Java和安卓类型,不应因为互操作性问题而需要来回转换。这不仅是处于性能方面的担心,在调试时也比较令人烦恼。最后,安 卓系统限制每个应用只能够使用65536个方法。因此,寻找Java的替代品时,一定不能在应用中添加大的标准SDK,因为这样会大大减少开发人员所能使 用的方法数量。举例来说,使用Groovy的SDK会增加8000多个方法。

Xtend——安卓开发的完美解决方案?

Xtend能够转化成地道的Java源代码,并且基本上只依赖于JDK和安卓系统的类。在运行时,也没有间接寻址、转换或者其他任何额外的开销。也 就是说,Xtend代码能够和Java的源代码有着基本一致的运行速度。另外,Xtend还包含一个经过精简的为安卓系统提供的运行时库,只有275kb 大小并且几乎包含了你所需要的一切。Xtend Eclipse插件与ADT(安卓开发工具)的整合也相当完美,对于新的安卓构建系统3,甚至还提供了相应的Gradle插件2。接下来就让我们详细了解一下如何使用Xtend改善典型的安卓代码。

Hello安卓!

与往常一样,我们先看一个简单的Hello World示例程序:

class HelloWorldActivity extends Activity {        override protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState)              val button = new Button(this       button.text = "Say Hello!"          button.onClickListener = [            Toast.makeText(context, "Hello Android from Xtend!", Toast.LENGTH_LONG).show         ]         val layout = new LinearLayout(this)         layout.gravity = Gravity.CENTER         layout.addView(button)         contentView = layout     }   }  

对于Java开发者来说,这个例子使用了类Java的编程风格,因此第一眼看上去会非常熟悉。另外,你可能会注意到,示例中所用的API 100%来自于安卓SDK和JDK。

主要的区别在于:

  • 没有分号(分号是可选的)
  • 使用setter和getter访问对象属性
  • 属性的默认可见性(如,类默认是共有的)
  • 使用拉姆达表达式替代匿名类

在语言的特性方面,有很多地方可以深入探讨,不过在此之前,先让我们看一下如何将Xtend编译器与相应的Android构建过程整合在一起。

使用Gradle进行构建

对于目前最常用的三个构建系统:Maven,Gradle和Ant,Xtend都有相应的插件支持。谷歌最近为安卓项目引入了新的基于Gradle的构建系统。接下来我们看一下使用Gradle构建我们的“Hello World”项目需要做哪些工作。

本文假设你已经在系统中安装了最新版本的Gradle和安卓SDK并且正确的设置了ANDROID_HOME环境变量。同时,你已经将Gradle的/bin目录添加到了PATH环境变量中。

接下来需要将构建脚本“build.gradle”添加到你的Eclipse Android项目的根目录下,build.gradle文件样例如下:

buildscript {     repositories {        mavenCentral()     }     dependencies {        classpath 'com.android.tools.build:gradle:0.8.+'        classpath 'org.xtend:xtend-gradle-plugin:0.1.+'       }    apply plugin: 'android'   apply plugin: 'xtend-android'     repositories {     mavenCentral()   }     dependencies {     compile ('org.eclipse.xtend:org.eclipse.xtend.lib:2.6.+')   }     android {      compileSdkVersion 19      buildToolsVersion "19.1.0"     sourceSets {         main {            manifest {               srcFile 'AndroidManifest.xml'            }            java {               srcDir 'src'            }            res {               srcDir 'res'            }            assets {               srcDir 'assets'            }            resources {               srcDir 'src'            }            aidl {               srcDir 'src'            }         }      }   }  

其主要工作就是导入并调用Maven和Xtend的构建插件。此外,我们将运行时库添加到项目中并告知Android插件我们正在使用 Eclipse风格的项目布局。上述工作完成后,在命令行窗口中进入项目的根目录并运行“gradle build”,Gradle将为你完成剩余的所有工作。

深入Xtend

除了语法糖之外,Xtend还附带了许多非常有用的语言特性,例如操作符重载,模板表达式和switch表达式。而且还可以通过结合不同的功能创建 新的特性。例如,假如你需要动态的UI,不能用静态的XML文件构建,而需要声明式的编写。Xtend为开发者提供了构建器语法(builder syntax)的支持。“Hello World”实例的UI实现代码如下:

import static extension com.example.helloworld.UiBuilder.*     class HelloWorldActivity extends Activity {        override protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState)           contentView = linearLayout [            gravity = Gravity.CENTER            addButton("Say Hello!") [               onClickListener = [                  Toast.makeText(context,                                 "Hello Android from Xtend!",                                 Toast.LENGTH_LONG).show               ]           ]       ]       }  

linearLayout(Context ctx, (LinearLayout)=>void initializer) 和button(ViewGroup group, String name, (Button)=>void initializer) 两个方法作为扩展被引入到Activity中。这两个方法将拉姆达函数作为其参数之一。传入拉姆达函数中的参数被称为implicit it,与this类似,implicit it不需要显式地解引用。如上所示,拉姆达函数,扩展方法和implicit it结合使用能够产生非常漂亮的构建器语法。通过Xtend也可以构建许多其他漂亮的API,从而以一种易读的声明式的方式编写代码。

来自于XML地狱的问候!

安卓开发者的相当一大部分日常工作就是配置和开发各种XML文件,用作国际化字符串的资源或用于各类视图的声明。安卓平台推荐使用XML文件,因为 平台已经为开发者提供了针对大型设备和SDK碎片化的解决方案。然而应用程序最终不可能只由静态视图和数据组成。开发者需要将所有的素材组合并为其赋予生 命。在安卓平台,通过R类来完成这些工作。这个自动生成的类包含了许多对应在XML文件中声明的各种元素的整型常量。假设一个视图XML文件中声明了如下 两个元素,点击Button可以更新TextView中的消息:

<TextView android:id="@+id/message_view"  android:layout_weight="1"  android:layout_width="0dp"  android:layout_height="wrap_content"  android:hint="@string/empty" >  <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:onClick="sayHello"  android:text="@string/hello_world" >  </Button>  

典型的安卓式开发方法是通过R类中生成的常量获取到TextView的控制权然后实现onClick的回调方法“sayHello”:

class HelloWorldActivity extends Activity {        TextView messageView        override protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState)         // set the view using the int constant         contentView = R.layout.main         // get a handle on the TextView         messageView = findViewById(R.id.message_view) as TextView      }        /**        * Callback automagically called by Android        */      def void sayHello(View v) {        messageView.text = "Hello Android from Xtend!"      }   }  

上面一段安卓的典型代码中包含了不安全的类型转换,命名规范和各种样板文件。用Xtend我们能够做得更好。

你好,Xtendroid!

Xtendroid4是一个专门为安卓开发提供类库以及所谓的积极注解(active annotation)的小型项目。积极注解可以理解为编译时的宏,它能够参与到从Xtend到Java转化的编译过程中。你可以随意修改被注解的类,生成附加类型或使用这个钩子读写纯文本文件。

这样只要有一个注释,我们就知道要绑定哪个视图并且注释还可以帮助我们生成样板文件。除此之外,它还能够提供类型安全的元素访问方法和回调方法。下面一段代码就是用Xtendroid的@AndroidActivity注释编写的Activity类。

@AndroidActivity(R.layout.main) class HelloWorldActivity {        /**        * Type safe callback        */      override void sayHello(View v) {         messageView.text = "Hello Android from Xtend!"      }   }  

现在,这个Activity中只包含了我们想要加入的行为。其他的设置都是自动实现的,例如设置管道绑定、内容视图或扩展Activity的样板文件。而且现在一切都是类型安全的,IDE能够了解其中的来龙去脉并为开发者提供适当的自动完成建议。

此外,Xtendroid还能够为开发者处理JSON对象,资源文件或SQLite数据库提供便利。而且,积极注解以库的形式存在,因此通过自行开发或定制化已有库的方式,开发者可以很容易地构建更适于自己的库。

从下方1下载Eclipse并使用更新站点5安装ADT就可以开始自己亲自尝试上面所讲的内容。Xtendroid项目包含许多类似本文中所展示的示例。最后祝大家能从中找到乐趣。

  1. Eclipse Xtend
  2. Xtend Gradle 插件
  3. Android Gradle 插件
  4. Xtendroid
  5. ADT 更新站点

关于作者

Niklas Therning是开源项目RoboVM的创建者和的联合创始人——RoboVM项目的主要贡献者。他把如何合理地将Java引入iOS平台作为其使命。开始RoboVM项 目前,Niklas参与创建了SpamDrain反垃圾邮件服务,并且作为其承包商,主要从事Java EE和web应用程序开发的工作。Niklas持有位瑞典哥德堡查尔姆斯理工大学的计算机科学理学硕士学位。可以通过Twitter账号@robovm关注他。

Sven Efftinge是一个充满激情的软件开发人员,他喜欢风筝冲浪运动、音乐和美食。他是Xtext项目的领导人。Xtext是一个程序设计语言、领域特定语言和JVM静态类型程序设计语言Xtend的开发框架。在位于Kiel的itemis公司,Sven领导一个研究部门。

过去几年,移动应用席卷了整个世界,在工作和生活的方方面面改变着我们使用互联网的方式。创建移动应用的各种技术也随之兴起,各种开发流程也 将移动应用视为一等公民,开始考虑适应移动开发的流程。尽管已经让人感觉无处不在,真正的移动应用时代才刚刚开始。我们即将面对新一代的移动设备,如可穿 戴设备或组成物联网的各种各样的移动装置。我们将面临全新的用于数据展示和命令接收的用户交互接口。我们也认识到越来越多的公司将真正采取移动优先的战 略。所有的这些都将对我们未来几年设计、开发和测试软件的方式产生巨大影响。

译文原文:另辟蹊径创建移动应用

查看英文原文:Unusual Ways to Create a Mobile App

转载于:https://my.oschina.net/yuanxulong/blog/322659

相关文章:

从0开始,基于Python探究深度学习神经网络

来源 | Data Science from Scratch&#xff0c; Second Edition作者 | Joel Grus全文共6778字&#xff0c;预计阅读时间50分钟。深度学习1. 张量2. 层&#xff08;Layer&#xff09;的抽象3. 线性层4. 神经网络作为一个层的序列5. 损失和优化6. 示例&#xff1a;XOR 重新…

ASP.NET2.0雷霆之怒盗链者的祝福【月儿原创】

ASP.NET2.0雷霆之怒盗链者的祝福 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.3.28 所谓盗链就是指其他网站把我们站点的文件链接帖到他们站上&#xff0c;这样白白占用我们的带宽。访问对于网站盗链行为&am…

数通手稿留档——BGP

本文转自Grodd51CTO博客&#xff0c;原文链接&#xff1a;http://blog.51cto.com/juispan/1954062&#xff0c;如需转载请自行联系原作者

ASP.NET2.0打通文件图片处理任督二脉【月儿原创】

ASP.NET2.0打通文件图片处理任督二脉 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.1 1.最简单的单文件上传(没花头)2.多文件上传3.客户端检查上传文件类型(以上传图片为例)4.服务器端检查上传文件类型(以上…

PaaS变厚了

通过与包括东方通等在内的众多厂商的合作&#xff0c;华云数据的运营型PaaS变得越来越厚实。借助PaaS Plus的推出&#xff0c;华云数据要把云化的工作前移&#xff0c;在产品开发和测试阶段就开始云化&#xff0c;这会让传统企业的云化取得更好的效果。“PaaS是个筐&#xff0c…

国内首个零信任技术标准发布 腾讯安全牵头编制

7月7日&#xff0c;中国电子工业标准化技术协会发布了国内首个零信任技术实现标准——T/CESA 1165-2021《零信任系统技术规范》团体标准&#xff0c;填补了国内零信任领域的技术标准空白。 &#xff08;《零信任系统技术规范》&#xff09; 据悉&#xff0c;该标准由腾讯安全牵…

集群概述及原理笔记(1)

it你好linux学习文档之集群概述及原理笔记(1) 一 前言 目前&#xff0c;越来越多的网站采用Linux操作系统&#xff0c;提供邮件、Web、文件存储、数据库等服务。也有非常多的公司在企业内部网中利用Linux服务器提供这些服务。随着人们对Linux服务器依赖的加深&#xff0c;对其…

ASP.NET2.0 遍历文件夹下所有图片【月儿原创】

ASP.NET2.0 遍历文件夹下所有图片 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.4 1.以下目录有若干图片&#xff08;都是大图片&#xff09; 2.在页面展现效果图 3.代码 后台代码using System;using Sy…

如何看待那些互相矛盾的论文?

原文&#xff1a;How to Make Sense of Contradictory Science Papers作者&#xff1a;Haixin Dang&#xff08;利兹大学博士后研究员&#xff09;、Liam Kofi Bright&#xff08;伦敦经济学院的哲学系助理教授&#xff09;译者&#xff1a;武文浩相信你已经读到过一些相互矛盾…

gdb图形化调试工具总结

gdb除了命令行方式等的调试之外&#xff0c;还有图形化的调试工具&#xff0c;下面列举一些供参考 1&#xff1a;insight 2: ddd 3: kgdb 4: xxgdb 其它的工具欢迎补充

ATLAS入门篇之CascadingDropDown控件编程

一、引言本文将通过具体的步骤解释如何借助于数据库&#xff08;Microsoft SQL Server 2005 Express Edition&#xff09;数据创建一个ASP.NET AJAX 1.0 CascadingDropDown控件。在本文示例中&#xff0c;我们将使用此层叠下拉列表框控件来选择要显示的汽车模型信息。【作者注】…

ASP.NET2.0 永恒密码之戒【月儿原创】

ASP.NET2.0 永恒密码之戒 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.8 1.我们经常有这样的情形&#xff1a; 就是用户注册时由于某个信息填写错误要重新填写。但是这个过程经过了服务器PostBack。所以密码…

GitHub 遭抵制!AI 代码生成神器竟成“抄袭工具”?

整理 | 郑丽媛出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;上周&#xff0c;微软、GitHub、OpenAI 三方联手推出的 AI 代码生成神器 GitHub Copilot 一经官宣便引起巨大关注&#xff1a;试问哪个开发者不想要这么一位“虚拟程序员”来解放自己的双手&#xff1f…

LAMP的安装及Xcache的配置

LAMP是LinuxApacheMySQLPHP的简称&#xff0c;意指以Linux作为服务器的操作系统&#xff0c;以Apache的HTTPD作为Web服务器&#xff0c;以PHP作为动态网页的解释器&#xff0c;以MySQL作为后端数据库管理系统&#xff0c;由此而搭建起来的一套Web服务器系统。为方便起见&#x…

Windows Server 2003 AD升级到Windows Server 2008 AD的方法及详细步骤

前言&#xff1a; Windows Server 2008 是现在企业比较流行的服务器操作系统&#xff0c;安全性高&#xff0c;配置灵活、方便&#xff0c;集成了Hyper-V虚拟化功能&#xff0c;能够充分发挥硬件的性能。Windows Server 2008改写了底层的网络传输代码&#xff0c;理论上&#x…

ASP.NET2.0 ReportingServices使用详解

ASP.NET2.0 ReportingServices使用详解 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.9本文先做个简单介绍&#xff0c;更多关于ReportingServices的文章见后续。 1.打开BIDS,这是报表开发工具 2.新建项目 3.选择…

输出程序运行的时间(精确到微秒)

对于要求性能的代码&#xff0c;输出程序运行的时间还是很有必要的&#xff0c;而且需要较高的精确度&#xff0c;下面这个代码段就实现了此功能 注意&#xff1a;只限于Linux下使用&#xff0c;因为<sys/time.h>的缘故 1 #include <sys/time.h>2 #include <ios…

售前比售后机器人控制逻辑更复杂,仅凭大规模数据后发优势难赶超!

实现人与机器的自然交互&#xff0c;一直以来都是全世界人类的共同愿望&#xff0c;无数科学家倾尽毕生精力致力于实现这个目标。语言&#xff0c;作为人与外界交流最有效的工具&#xff0c;成为机器智能的重点研究对象&#xff0c;而对话型机器人则成为实现人机交互最早的突破…

JAVAEclipse:could not find the main class,program will exit!

JAVAEclipse:could not find the main class,program will exit! 遇到这个错误主要是当前的工程的jdk与eclipse的版本配置不匹配造成的&#xff0c;修改方法如下&#xff1a; 在当前工程点右键选择Properties->Java Compiler->选中Enable project specific settings->…

ASP.NET2.0 文本编辑器FCKeditor的冰冷之心 【月儿原创】

ASP.NET2.0 文本编辑器FCKeditor的冰冷之心 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.9 FCKeditor是目前最好的html文本编辑器&#xff0c;如果还不明白的话看了下图就知道了效果图: 那么为什么说是FC…

转:strcat与strcpy与strcmp与strlen

转自&#xff1a;http://blog.chinaunix.net/uid-24194439-id-90782.html strcat 原型&#xff1a;extern char *strcat(char *dest,char *src);用法&#xff1a;#include <string.h>功能&#xff1a;把src所指字符串添加到dest结尾处(覆盖dest结尾处的\0)并添加\0。说明…

2021 EdgeX中国挑战赛盛大开幕,英特尔赋能开发者,助力创新方案落地

2021年7月12日&#xff0c;北京中关村论坛隆重举行。论坛上&#xff0c;英特尔研究院副总裁、英特尔中国研究院院长宋继强博士&#xff0c;北京市科委、中关村管委会高科技产业促进中心主任徐剑发表致辞并联合Linux基金会、VMware威睿等单位代表共同宣布2021 EdgeX中国挑战赛开…

构建安全的 ASP.NET 应用程序

最近开发的系统因为用到Asp.net的安全性方面的东西&#xff0c;所以拼命看MSDN&#xff0c;E文看着有点慢&#xff0c;还好现在在MSDN 中文网站中很多文章都有了翻译&#xff0c;所以今天索性在MSDN中文网站上找了一把&#xff0c;还真有。有感兴趣的朋友可以看看&#xff0c;不…

.NET2.0隐形的翅膀,正则表达式搜魂者【月儿原创】

.NET2.0隐形的翅膀&#xff0c;正则表达式搜魂者 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.14 本文实现了&#xff1a;只能输入1个数字只能输入n个数字只能输入至少n个数字只能输入m到n个数字只能输入数…

连华为都在研究的计算机视觉,到底有多牛?

去年&#xff0c;华为在CCF-GAIR 大会上介绍了在人工智能领域的愿景&#xff0c;华为为了实现这个战略目标&#xff0c;从中梳理出深耕基础研究、打造全栈方案、投资开放生态和人才培养、解决方案增强、内部效率提升五大方向&#xff0c;以此打造无所不及的AI&#xff0c;构建万…

JS 点击弹出图片/ 仿QQ商城点击左右滚动幻灯片/ 相册模块,点击弹出图片,并左右滚动幻灯片...

1&#xff0c; 点击弹出图片 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"><head><meta ht…

Nginx+Tomcat实现反向代理与动静分离

1. 什么是动静分离 所谓动静分离就是通过nginx&#xff08;或apache等&#xff09;来处理用户端请求的静态页面&#xff0c;tomcat&#xff08;或weblogic&#xff09;处理动态页面&#xff0c;从而达到动静页面访问时通过不同的容器来处理。 2. 为什么做动静分离 Nginx处理静态…

白话经典算法系列之七 堆与堆排序

堆排序与高速排序&#xff0c;归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前&#xff0c;先解说下什么是数据结构中的二叉堆。二叉堆的定义二叉堆是全然二叉树或者是近似全然二叉树。二叉堆满足二个特性&#xff1a;1&#xff0e;父结点的键值总是大…

.NET2.0抓取网页全部链接【月儿原创】

.NET2.0抓取网页全部链接 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.18 该方法经过对各大门户网站测试结果是抓取率100%&#xff01; 效果图 后台代码&#xff1a; using System;using System.Data;…

腾讯会议又一黑科技,屏蔽超过 200 种会议噪声是如何做到的?

作者 | 伍杏玲出品 | AI 科技大本营&#xff08;ID:rgznai100&#xff09;远程会议已成为我们常规的工作沟通方式&#xff0c;在线交流打破时间、空间的限制&#xff0c;给予我们便利之际&#xff0c;也屡遭尴尬&#xff1a;忘记静音&#xff0c;一边听会一边敲键盘&#xff0c…