Flux--Hello World

这是一个极简的HelloWorld应用,主要用来展示如何在Android平台架构Flux应用。并提供一些基础代码,方便开发者直接Copy这些代码到自己的工程中,省掉重新造轮子的过程。代码地址在Flux-HelloWorld,接下来会一步步的解释这个应用是如何构建的。

Demo程序是用AndroidStudio开发的,假设你已经了解Android和AndroidStudioIDE,如果你已经很熟悉Android应用的开发,看完AndroidFlux一览或许已经可以开发出基于Flux框架的应用,如果你并不熟悉Flux或者Android,务必先读完这篇文档

源码结构 

本着架构即目录的思想,让我们先看一下源码结构,整个的源码结构是这样的:


这里包含4个目录和一个文件:

  1. MainActivity.java Flux框架中的Controller-View部分,在Android中可以是Activity或者Fragment
  2. actions Flux框架中的Action部分,存放不同类型的XXXAction.javaActionsCreator.java文件
  3. dispatcher Flux框架中的Dispatcher部分,存放 Dispatcher.java 文件,一个应用中只需要一个Dispatcher
  4. model 存放各种业务逻辑相关的Model文件
  5. stores Flux框架中的Stores部分,存在各种类型的 XXXStore.java 文件

创建一个Dispatcher 

在AndroidFlux中Dispatcher是就是一个发布-订阅模式。Store会在这里注册自己的回调接口,Dispatcher会把Action分发到注册的Store,所以它会提供一些公有方法来注册监听和分发消息。

/** * Flux的Dispatcher模块 * Created by ntop on 18/12/15. */public class Dispatcher { private static Dispatcher instance ; private final List<Store > stores = new ArrayList< > ( ) ; public static Dispatcher get ( ) { if (instance == null ) { instance = new Dispatcher ( ) ; } return instance ; } Dispatcher( ) { } public void register(final Store store ) { stores . add(store ) ; } public void unregister(final Store store ) { stores . remove(store ) ; } public void dispatch(Action action ) { post(action ) ; } private void post(final Action action ) { for (Store store : stores ) { store . onAction(action ) ; } } }

Dispatcher对外仅暴露3个公有方法:

  1. register(final Store store) 用来注册每个Store的回调接口
  2. unregister(final Store store) 用来接触Store的回调接口
  3. dispatch(Action action) 用来触发Store注册的回调接口

这里仅仅用一个ArrayList来管理Stores,对于一个更复杂的App可能需要精心设计数据结构来管理Stores组织和相互间的依赖关系。

创建Stores 

这里使用EventBus来实现Store,EventBus的主要功能是用来给Controller-View发送change事件:

/** * Flux的Store模块 * Created by ntop on 18/12/15. */public abstract class Store { private static final Bus bus = new Bus ( ) ; protected Store( ) { } public void register(final Object view ) { this .bus . register(view ) ; } public void unregister(final Object view ) { this .bus . unregister(view ) ; } void emitStoreChange( ) { this .bus . post( changeEvent( ) ) ; } public abstract StoreChangeEvent changeEvent( ) ; public abstract void onAction(Action action ) ; public class StoreChangeEvent { } }

抽象的Store类,提供了一个主要的虚方法 void onAction(Action action) ,这个方法是注册在Dispatcher里面的回调接口,当Dispatcher有数据派发过来的时候,可以在这里处理。

下面看一下更具体的和业务相关的MessageStore类:

/** * MessageStore类主要用来维护MainActivity的UI状态 * Created by ntop on 18/12/15. */public class MessageStore extends Store { private static MessageStore singleton ; private Message mMessage = new Message ( ) ; public MessageStore( ) { super( ) ; } public String getMessage( ) { return mMessage . getMessage( ) ; } @Override @Subscribe public void onAction(Action action ) { switch (action . getType( ) ) { case MessageAction .ACTION_NEW_MESSAGE : mMessage . setMessage( (String ) action . getData( ) ) ; break ; default : } emitStoreChange( ) ; } @Override public StoreChangeEvent changeEvent( ) { return new StoreChangeEvent ( ) ; } }

在这里实现了 onAction(Action action) 方法,并用一个switch语句来路由各种不同的Action类型。同时维护了一个结构 Message.java 类,这个类用来记录当前要显示的消息。Store类只能通过Dispatcher来更新(不要提供setter方法),对外仅暴露各种getter方法来获取UI状态。这里用String getMessage()方法来获取具体的消息。

在Controller-View里面处理“change”事件 

在Android中,Flux的Controller-View对应于Activity或者Fragment,我们需要在这里注册Strore发生改变的事件通知,以便在Store变化的时候重新绘制UI。

/** * Flux的Controller-View模块 * Created by ntop on 18/12/15. */public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText vMessageEditor ; private Button vMessageButton ; private TextView vMessageView ; private Dispatcher dispatcher ; private ActionsCreator actionsCreator ; private MessageStore store ; @Override protected void onCreate(Bundle savedInstanceState ) { super . onCreate(savedInstanceState ) ; setContentView(R .layout .activity_main ) ; initDependencies( ) ; setupView( ) ; } @Override protected void onDestroy( ) { super . onDestroy( ) ; dispatcher . unregister(store ) ; } private void initDependencies( ) { dispatcher = Dispatcher . get ( ) ; actionsCreator = ActionsCreator . get (dispatcher ) ; store = new MessageStore ( ) ; dispatcher . register(store ) ; } private void setupView( ) { vMessageEditor = (EditText ) findViewById(R .id .message_editor ) ; vMessageView = (TextView ) findViewById(R .id .message_view ) ; vMessageButton = (Button ) findViewById(R .id .message_button ) ; vMessageButton . setOnClickListener( this ) ; } @Override public void onClick(View view ) { int id = view . getId( ) ; if (id == R .id .message_button ) { if (vMessageEditor . getText( ) ! = null ) { actionsCreator . sendMessage(vMessageEditor . getText( ) . toString( ) ) ; vMessageEditor . setText( null ) ; } } } private void render(MessageStore store ) { vMessageView . setText(store . getMessage( ) ) ; } @Override protected void onResume( ) { super . onResume( ) ; store . register( this ) ; } @Override protected void onPause( ) { super . onPause( ) ; store . unregister( this ) ; } @Subscribe public void onStoreChange(Store .StoreChangeEvent event ) { render(store ) ; } }

这部分的代码比较多,首先在 onCreatre(...) 方法中初始化了依赖和需要的UI组件。最重要的是 onStoreChange(...) 方法,这个方法是注册在Store中回调(使用EventBus的@Subscribe注解标识),当Store发生变化的时候会触发这个方法,我们在这里调用render()方法重绘整个界面。

创建Action 

Action是简单的POJO类型,只提供两个字段:type 和 data, 分别记录Action的类型和数据。注意Action一旦创建是不可更改的, 所以它的字段类型修饰为final类型。

public class Action<T > { private final String type ; private final T data ; Action(String type , T data ) { this .type = type ; this .data = data ; } public String getType( ) { return type ; } public T getData( ) { return data ; } }

下面是一个业务相关的Action实现:

public class MessageAction extends Action<String > { public static final String ACTION_NEW_MESSAGE = "new_message" ; MessageAction(String type , String data ) { super(type , data ) ; } }

这个实现非常简单,仅仅多定义了一个Action类型字段:public static final String ACTION_NEW_MESSAGE = "new_message"。如你所见,Action都是这么简单的,不包含任何业务逻辑。

创建ActionCreator 

ActionCreator 是Flux架构中第“四”个最重要的模块(前三:Dispatcher、Store、View),这里实际上处理很多工作,提供有一个有语义的API,构建Action,处理网络请求等。

/** * Flux的ActionCreator模块 * Created by ntop on 18/12/15. */public class ActionsCreator { private static ActionsCreator instance ; final Dispatcher dispatcher ; ActionsCreator(Dispatcher dispatcher ) { this .dispatcher = dispatcher ; } public static ActionsCreator get (Dispatcher dispatcher ) { if (instance == null ) { instance = new ActionsCreator (dispatcher ) ; } return instance ; } public void sendMessage(String message ) { dispatcher . dispatch( new MessageAction (MessageAction .ACTION_NEW_MESSAGE , message ) ) ; } }

此处提供了一个 sendMessage(String message) ,就像名字暗示的那样,这个方法用来发送消息(到Store)。在方法内部,会创建一个MessageAction来封装数据和Action类型,并通过Dispatcher发送到Store。

Model 

无论是基于哪种框架的应用都需要Model模块,在这个简单的“HelloWorld”应用中,其实用一个String即可传递消息,但是为了架构的完整和更好的语义表达,定义一个Message类型封装一个String字段作为Model。

希望通过这个简单的HelloWorld应用,能够让你一窥Flux的面貌。

转载地址:http://androidflux.github.io/docs/helloworld.html#content

在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
05-30
在Reactor库中,`Flux`是一种异步执行的多个结果的数据流,它类似于Java中的`Stream`。`Flux`可以让您更轻松地处理和转换数据流,以及处理来自外部数据源的事件。 `Flux`可以使用多个方式创建,例如使用静态方法、使用`Iterable`或`Stream`、从`Mono`转换等。以下是一个使用静态方法创建`Flux`的示例: ```java import reactor.core.publisher.Flux; public class FluxExample { public static void main(String[] args) { Flux.just("Hello", "World") // 创建一个包含两个字符串的Flux .subscribe(System.out::println); // 订阅Flux并在元素可用时打印它们 } } ``` 在上面的代码中,我们使用`Flux.just`方法创建了一个包含两个字符串的`Flux`,然后使用`subscribe`方法来订阅它并在元素可用时打印它们。 `Flux`还提供了许多其他方法,可以用于创建、转换和组合`Flux`。例如,您可以使用`map`方法将`Flux`中的元素转换为另一种类型,或使用`merge`方法将多个`Flux`合并为一个。以下是一个使用`map`和`merge`的示例: ```java Flux<String> flux1 = Flux.just("Hello", "World"); Flux<String> flux2 = Flux.just("Reactor", "Flux"); Flux<String> result = Flux.merge(flux1.map(String::toUpperCase), flux2.map(String::toLowerCase)); result.subscribe(System.out::println); // 输出 "HELLO", "WORLD", "reactor", "flux" ``` 在上面的代码中,我们首先使用`map`方法将`flux1`和`flux2`中的字符串转换为大写和小写,然后使用`merge`方法将它们合并为一个`Flux`。最后,我们订阅了`result`并打印了它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值