首页 文章 精选 留言 我的

精选列表

搜索[规划能力],共10003篇文章
优秀的个人博客,低调大师

红帽破坏生态,AlmaLinux 公布未来规划

AlmaLinux 是一个基于 Red Hat Enterprise Linux(RHEL)的克隆版本,由 CloudLinux 公司发起创建。AlmaLinux 是在红帽决定停止开发 CentOS(非 Stream 版本)之后才建立的,它的开发始于 2020 年 12 月,第一个正式版本在 2021 年 3 月发布。 AlmaLinux 采用 RHEL 8 作为其基础,AlmaLinux 的源代码完全兼容 RHEL,这意味着用户可以在 AlmaLinux 上运行在 RHEL 上运行的所有应用程序和工具。 昨天红帽发出公告,表示将限制对 RHEL 源代码的访问,未来 CentOS Stream 将成为公共 RHEL 相关源代码发布的唯一仓库。对于红帽的客户和合作伙伴,依然可以根据其订阅协议通过 Red Hat Customer Portal 获得源代码。 在事件发生后,AlmaLinux 第一时间就在社交平台表示将研究这个改动对他们的影响。经过一天时间研究,他们发布了声明,公布了未来的一些计划。 昨天,红帽宣布了一项巨大的转变,影响了 RHEL 的所有重构建和分支。今后红帽将只在其 Red Hat Customer Portal 中发布 RHEL RPM 的源代码 。由于所有 RHEL 克隆都依赖于发布的源代码,这对整个红帽生态再次造成了破坏。 实际上,在红帽进行此次变动之前,AlmaLinux 就已经注意到了一些不寻常的地方。在上周,AlmaLinux 发现 Red Hat 8 的一些更新没有像以往那样在 git.centos.org 上发布。他们一开始以为这是一个错误,并向红帽提交了一份报告,但这个问题一直没有得到解决。直到他们看到红帽发出的公告才得到答案。 这一变化意味着,我们作为 RHEL克隆的构建者,现在除了要遵守软件源中所包含的许可和协议外,还要负责遵守围绕红帽接口的许可和协议。不幸的是,按照我们今天的理解,红帽的用户接口协议表明,重新发布通过 Red Hat Customer Portal 获得的资源将违反这些协议。 这意味着我们需要一个新的解决方案。 在短期内,他们的计划是提取 CentOS Stream 和 Oracle Linux 更新,以确保 AlmaLinux 可以获得持续的安全补丁。这可以确保它们与 RHEL 1:1 兼容,同时不违反红帽的许可。但从长远来看,他们将与其他 RHEL 下游产品和合作伙伴一起寻找合适的发展道路。 延伸阅读:红帽限制 RHEL 代码访问,瞄准 Rocky Linux 和 AlmaLinux

优秀的个人博客,低调大师

使用Roboguice依赖注入规划Android项目

关于依赖注入 Dependency Injection( 依赖注入)能够非常好的帮助我们分离模块。减少耦合、提高可測试性。(PS:Roboguice 仅仅是一个工具。依赖注入很多其它的是一种思想) 通常博主开发项目时喜欢以Activity 、Service 等组件作为顶级层入口,辅以各类接口作为业务服务。Activity 主要负责维护界面相关的东西,及提供功能所须要的上下文环境,引入功能实现须要的接口。 这些接口的实例通过Roboguice进行注入。(当然你也能够全然不使用Roboguice,但还是建议保留接口注入的设计)。 关于Roboguice Roboguice 是基于guice-noaop 的android注入框架, 项目地址:https://github.com/roboguice/roboguice.利用Roboguice能够较轻松的注入各种服务。它默认提供了各种android相关的注入如: injectView ,injectResource 等。 遗憾的是这里将不正确Roboguice的使用具体解说。想了解 Roboguice 的读者能够查看官网的Wiki或參考:http://www.imobilebbs.com/wordpress/archives/2480 须要注意的是Roboguice 分为 1.1 版和2.0及以上版本号。这两个版本号并不兼容。一般使用2.0就可以。更简单方便。 下载须要的包 可參考: https://github.com/roboguice/roboguice/wiki/InstallationNonMaven 项目创建 创建android项目命名为:RoboguicePractice ,并加入Roboguice 相关包。 基本功能 项目仅包括一个Activity,界面上包括一个TextView和Button.点击Button 可查看当前时间。 为了使Demo更具代表性。 Activity 须要引用 ITimeService 的接口来获取时间。 ITimeService 接口的详细实现类AndroidTimeReand则依赖于ITimeRepository(数据源),这样就从逻辑上划分出一个主要的三层。 通常我喜欢把数据相关的模块(db、sharepreferene、net、cache等)归类到Repository中,对上层而言就形成一个数据来源接口。 注意:没有哪一种设计是万能。须要依据最实际的情况,不断的进行权衡,终于选择较合适的系统设计,而且要做好睡着系统的成长须要变更设计的准备。 比如有的android程序比較简单。就全然不须要 IService 服务层。 项目包结构 这里创建一个ViewModel 用于辅助界面展示 使用静态类的实现方式 在正式開始项眼下让我们看看一种常见的实现——通过静态的方式为 Activity提供服务。 1publicclassAndroidTimeRead{ 2 3 public staticTimeViewModelshowTime(){ 4TimeViewModelmodel= newTimeViewModel(); 5model.setTime(String.valueOf(System.currentTimeMillis())); 6 returnmodel; 7} 8 9} 10 11 public classMainActivity extendsActivity{ 12 13 privateTextViewtxtShowTime; 14 privateButtonbtnShow; 15 16@Override 17 protected voidonCreate(BundlesavedInstanceState){ 18 super.onCreate(savedInstanceState); 19setContentView(R.layout.activity_main); 20 21txtShowTime=(TextView)findViewById(R.id.txtShowTime); 22btnShow=(Button)findViewById(R.id.btnShow); 23btnShow.setOnClickListener( newView.OnClickListener(){ 24 25@Override 26 public voidonClick(Viewv){ 27TimeViewModelviewModel=AndroidTimeRead.showTime(); 28txtShowTime.setText(viewModel.getTime()); 29} 30}); 31 32} 33 34} 代码非常easy,也实现了我们的基本须要(假设产品到此为止的话)。 但有两个明显的缺点,假设项目中大部分都是用了静态。那么面向OO的各种设计也就无法使用了。 还有一个问题是:当你想对MainActivity 进行单元測试,你会发现很困难。AndroidTimeRead 必须被包括进来,假设它还引用了其它的组件(如Db 或 net),那么这些组件也必须包括入内。静态类型由于一直在内存中,假设它引用了其它类型,则被引用的对象CG无法回收。 改进 这里我们将AndroidTimeRead 进行一些改进去掉令人讨厌的静态。 将AndroidTimeRead 改成单例。 1 public classAndroidTimeRead{ 2 3 private static classInstaceHolder{ 4 public staticAndroidTimeReadinstance= newAndroidTimeRead(); 5} 6 7 public staticAndroidTimeReadgetInstance(){ 8 returnInstaceHolder.instance; 9} 10 11 privateAndroidTimeRead(){} 12 13 publicTimeViewModelshowTime(){ 14TimeViewModelmodel= newTimeViewModel(); 15model.setTime(String.valueOf(System.currentTimeMillis())); 16 returnmodel; 17} 18 19} MainActivitry 进行相应的 1TimeViewModelviewModel=AndroidTimeRead.getInstance().showTime();调用改动 这里去掉了静态的方式,但是却没有解除直接依赖实现的问题。 关注行为 设计程序时,我们应该更加关注行为而非数据,简单的理解是尽可能面向接口编程。 在这里样例中基本的行为就是showTime. 因此我们定义一个接口 为MainActivity 提供所须要的行为(即提供给用户的服务)。 1 public interfaceITimeService{ 2TimeViewModelshowTime(); 3} MainActivity 上的改动: 1privateITimeServicetimeService; 2 // 提供注入点 3 public voidsetTimeService(ITimeServicetimeService){ 4 this.timeService=timeService; 5} 6 7@Override 8 protected voidonCreate(BundlesavedInstanceState){ 9 super.onCreate(savedInstanceState); 10setContentView(R.layout.activity_main); 11 12txtShowTime=(TextView)findViewById(R.id.txtShowTime); 13btnShow=(Button)findViewById(R.id.btnShow); 14btnShow.setOnClickListener( newView.OnClickListener(){ 15 16@Override 17 public voidonClick(Viewv){ 18TimeViewModelviewModel=timeService.showTime(); 19txtShowTime.setText(viewModel.getTime()); 20} 21}); 22 23} 这里 MainActivity 引用了 ITimeService,并通过 setTimeService 的方式提供注入点(重要)。 到此一个主要的结构已经形成。当我们须要对MainActivity进行測试时,能够通过 Mock<ITimeService> 方式。并使用setTimeService 注入到MainActivity 中,解除了与详细实现的依赖。 遗憾的是上面的程序不能正常执行。ITimeService 没有实例化。我们尽管提供了注入点。可是Activity 的生命周期由系统接管。我们无法直接使用。 聪明的读者可能已经想到。我们能够通过实现一个BaseActivity(继承至Activity)。然后在BaseActivity里提供IService 的实现。如 getService(class<?>) ,再让MainActivity 继承自BaseActivity。 其实当你使用Roboguice 时也是须要继承自其提供的RoboActivity。 完毕业务代码 在引入Roboguice 前先完毕Demo的结构。 加入ITimeRepository 和相应的实现。并让AndroidTimeRead 依赖 ITimeRepository。 1 public classTimeModel{ 2 public longCurrentTime; 3} 4 public interfaceITimeRepository{ 5TimeModelquery(); 6} ITimeRepository 的实现: public classTimeRepository implementsITimeRepository{ @Override publicTimeModelquery(){ TimeModelmodel= newTimeModel(); model.CurrentTime=System.currentTimeMillis(); returnmodel; } } 将 AndroidTimeRead 改动,让其从 ITimeRepository 中获取时间: public classAndroidTimeRead implementsITimeService{ privateITimeRepositoryrep; publicAndroidTimeRead(ITimeRepositoryrep){ this.rep=rep; } publicTimeViewModelshowTime(){ TimeViewModelmodel= newTimeViewModel(); model.setTime("如今的时间是"+String.valueOf(rep.query())); returnmodel; } } 能够发现。这里AndroidTimeRead 也是依赖于 ITimeRepository接口的。而且通过构造函数。提供了注入口。 新的时间获取方式的改动,并没有要求MainActivity 函数做不论什么改动。假设是直接使用AndroidTimeRead,则须要变更MainActivity。 引入Roboguice 应该放在哪里? 上面的代码都是与getTime() 业务相关的。而Roboguice 却是属于系统支持类。 一个真正的项目中一般会包括不少这种组件如:日志、行为打点等等。这里组件较明显的特征是与业务的关系度不大。甚至直接移除也不会影响功能的正常使用。 对于这些组件,我一般会以一种脚手架的设计方式。将它们组织起来,并为其提供系统接入点。 命名一个Infrastructure包。将须要的基础设施放置在此。 引入RoboActivity 将MainActivity 的父类改动为 RoboActivity。为View加入InjectView注入 1 public classMainActivity extendsRoboActivity{ 2 3@InjectView(R.id.txtShowTime) 4 privateTextViewtxtShowTime; 5@InjectView(R.id.btnShow) 6 privateButtonbtnShow; 7 8@Inject 9 privateITimeServicetimeService; 10 // 提供注入点 11 public voidsetTimeService(ITimeServicetimeService){ 12 this.timeService=timeService; 13} 14 15@Override 16 protected voidonCreate(BundlesavedInstanceState){ 17 super.onCreate(savedInstanceState); 18setContentView(R.layout.activity_main); 19 20btnShow.setOnClickListener( newView.OnClickListener(){ 21 22@Override 23 public voidonClick(Viewv){ 24TimeViewModelviewModel=timeService.showTime(); 25txtShowTime.setText(viewModel.getTime()); 26} 27}); 28 29} 因为 ITimeService 是我们自己定义的服务。须要为其指定实现。 创建RoboApplication 并继承自android 的Application同一时候改动AndroidManifest 里的配置。创建一个TimeModule类实现Module接口。 1 public classRoboApplication extendsApplication{ 2 3@Override 4 public voidonCreate(){ 5 super.onCreate(); 6RoboGuice.setBaseApplicationInjector( this,RoboGuice.DEFAULT_STAGE, 7RoboGuice.newDefaultRoboModule( this), newTimeModule()); 8} 9} setBaseApplicationInjector 最后一个參数是变參能够注冊多个Module 1 public classTimeModule implementsModule{ 2 3@Override 4 public voidconfigure(Binderbinder){ 5 // 顺序无关,在详细的Activity中被创建 6 binder 7.bind(ITimeService. class) 8.to(AndroidTimeRead. class); 9 // .in(Singleton.class); // 单件 10 11binder.bind(ITimeRepository. class) 12.to(TimeRepository. class); 13 14} 15 16} binder 用于指定接口和详细的实现的映射, 这里仍旧依赖一个问题,就是 AndroidTimeRead 对 ITimeRepository 的依赖须要指定。 这样的复杂类型须要使用Provider来指定。 能够直接在 TimeModule 加入例如以下方法: 1 @Provides 2AndroidTimeReadgetAndroidTimeRead(ITimeRepositoryrep){ 3 return newAndroidTimeRead(rep); 4} 主要是通过@Provides。 除此以外还能够通过实现Provider<T> 接口实现。 1 public classAndroidTimeReadProvider implementsProvider<AndroidTimeRead>{ 2 3@Inject 4ITimeRepositoryrep; 5 6@Override 7 publicAndroidTimeReadget(){ 8 9 return newAndroidTimeRead(rep); 10} 11 12} 相应的在 Module加入 AndroidTimeRead的Bind 1 @Override 2 public voidconfigure(Binderbinder){ 3 // 顺序无关,在详细的Activity中被创建 4 binder 5.bind(ITimeService. class) 6.to(AndroidTimeRead. class); 7 // .in(Singleton.class); // 单件 8 9binder.bind(ITimeRepository. class) 10.to(TimeRepository. class); 11 12binder.bind(AndroidTimeRead. class) 13.toProvider(AndroidTimeReadProvider. class); 14 15} 引入注入框架须要的思考: 1、对象的生命周期怎样控制:单例或 每次创建新对象? 2、框架的运行效率 3、其它可选择的框架如 dagger 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5061551.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册