Skip to content
This repository was archived by the owner on Apr 25, 2024. It is now read-only.

Namespaces

satchit8 edited this page Oct 21, 2016 · 38 revisions
This page contains a detailed description of neko namespaces describing most of the possible usages for each of them. To inspect all functions and their documentation see the Marginalia docs. /NOTE: This document assumes the reader to already have some knowledge of the/ /Android platform. Neko doesn't try to completely hide the Java side of/ /Android, neither it tries to replace the key Android concepts. If you start/ /learning Android through Clojure, it is a good idea to grab a regular/ /Java/Android book to accompany you./ ** neko.action-bar Provides utilities to modify application's action bar. For detailed information see [[https://github.com/clojure-android/neko/wiki/Action-bar][Action bar]] page. ** [[http://clojure-android.github.com/neko/#neko.activity][neko.activity]] This namespace stores facilities related to the Activity class. *** Defining an activity Since defining a new activity requires to inherit the Activity class, =defactivity= macro simplifies this work. This macro first takes optional arguments in key-value format, and then a list of different activity event handlers. For example: #+BEGIN_SRC clojure (defactivity your.package.name.MainActivity :key :main :features [:no-title] (onCreate [this bundle] (.superOnCreate this bundle) ...) (onResume [this] (.superOnResume this) ...)) #+END_SRC Any methods that override android.app.Activity methods, or implement any interfaces you provide, can be specified here. Examples include: - onCreateOptionsMenu - onStart - onStop - onActivityResult - etc. You must remember to manually call super methods where they are necessary. Also keep in mind that some methods have to return boolean values, e.g. =onCreateOptionsMenu= and =onOptionsItemSelected=. Another option you can use is =:features=. Followed by a vector of keywords, it will call =(request-window-features!)= on it as the first thing in =:onCreate=. You can also use special =:key= option to assign a unique keyword to activity. The activity can be later retrieved by that keyword via =(neko.debug/*a keyword)=. You can also simply call =(*a)= from inside the namespace where activity is defined. For example: #+BEGIN_SRC clojure (require '[neko.debug :refer [*a]]) (defactivity org.bar.foo.MainActivity :key :main ...) (*a :main) ;=> returns MainActivity instance (*a) ;=> returns MainActivity when in the same namespace #+END_SRC Keep in mind that is a debug-time feature, and you should not leave code that relies on =(*a)= in production. This macro may return a paused/stopped activity which can lead to undefined behavior, or even yield nil. So for the release build use the activity instance provided as first argument to methods (=this=) and properly pass it to your functions that operate on the Activity. *** Other useful functions =set-content-view!= takes an activity and sets its content view to be one of the following: - neko.ui tree - View instance - layout ID defined in XML If UI tree is provided, =make-ui= will be called upon it automatically. =request-window-features!= requests the given features for the activity. The features should be keywords such as =:no-title= or =:indeterminate-progress= corresponding FEATURE_NO_TITLE and FEATURE_INDETERMINATE_PROGRESS, respectively. Returns a sequence of boolean values corresponding to each feature, where a true value indicates the requested feature is supported and now enabled. This function should be called before =set-content-view!=. You might as well just specify a vector of features in =:features= option in =defactivity=. *** Fragments =simple-fragment= function allows you to create a trivial Fragment object that contains specified view. Takes optional context and a View object or neko.ui tree. #+begin_src clojure (simple-fragment [:linear-layout {:orientation :vertical} [:text-view {:text "Text"}] [:button {:text "Button"}]]) #+end_src ** [[http://clojure-android.github.com/neko/#neko.context][neko.context]] You can always access the application instance (root context of the application) in =neko.App/instance= field. *** Getting system services : (get-service :alarm) ;; or : (get-service context :alarm) is the same as calling: : (.getSystemService context Context/ALARM_SERVICE) ** [[http://clojure-android.github.com/neko/#neko.data][neko.data]] Provides functions to read data from Bundles, SharedPreferences and Intents. *** Extracting data from objects classes like from maps =like-map= function when called instance of the above-mentioned classes returns a thin wrapper around it that allows treating the object like a map (in destructuring, for example). : (defactivity ... : (onCreate [this bundle]) : ... : (let [{:keys [sharks-count lazers?]} (like-map bundle)] ...)) Note that you can use only keywords to extract values. So =(get (like-map bundle) :foo)= is equal to =(get (like-map bundle) "foo")=. /Warning: an instance wrapped with =like-map= cannot be used as an original one. So for example, if you need to pass =bundle= to another activity, you have to use the original instance and not the wrapped one./ ** neko.data.shared-prefs *** defpreferences The most convenient way to work with SharedPreferences is via =defpreferences= macro. It defines an atom with a hashmap, and binds the named SharedPreferences object to it. The atom is watched, so whenever you make changes to it, the underlying SP is updated automatically. In other words, you get an atom with persistent state across application restarts.
(defpreferences prefs "my_sp_file")

(swap! prefs assoc :user "dummy")

;; Later, application is restarted

(:user @prefs)
;=> "dummy"
Keep in mind that because SharedPreferences is limited in what it can keep (primitives and Strings), the same applies to the atom. Putting invalid data into the atom will lead to errors and inconsistencies. For keys you must use only Clojure keywords or Strings. Be aware not to use a wrapped SharedPreferences file explicitly to avoid inconsistencies. *** Low-level functions =get-shared-preferences= function returns a SharedPreferences object for the given name and access mode. Available modes: =:private=, =:world-readable= and =:world-writeable=. : (def prefs (get-shared-preferences "my_preferences" :private)) Then you can extract primitive values from the retrieved object by wrapping it with =like-map=. To store a value inside the SharedPreferences object =put= function is used. It takes a SharedPreferences.Editor object, a key and a value. The key could be either a string or a keyword. : (-> (.edit prefs) : (put :sharks-count 5) : (put :sharks-hungry false) : .commit) ** [[http://clojure-android.github.com/neko/#neko.data.sqlite][neko.data.sqlite]] Provides convenient method of working with SQLite databases. See detailed description on the [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite][dedicated page]]. ** [[http://clojure-android.github.com/neko/#neko.debug][neko.debug]] Contains convenience tools to be used while developing the application. *** Getting activity contexts from REPL While developing it can be useful to get hold on activity Context in the REPL, not just inside activity callbacks. =*a= is a macro for that. See [[https://github.com/clojure-android/neko/wiki/Namespaces#nekoactivity][neko.activity]] docs for usage explanation and example. *** Safely handling UI exceptions By default the application crashes if the code that was running on the UI thread throws an unhandled exception. This greatly reduces productivity as you have to rerun your application and re-evaluate all new forms. Wrapping the code with =safe-for-ui= macro ensures that the missed exception won't be so disastrous. : (safe-for-ui (/ 1 0)) =neko.threading/on-ui= uses this macro to wrap its code by default, so in most cases you can use it instead of =safe-for-ui=. This works only in debug mode, and exceptions will still crash the app in release, so you will be able to normally get crash reports in case of a bug. When an exception or error happens in the code wrapped with =safe-for-ui=, you will see a Toast notifying you what happened. You can get the Throwable object to examine it in more detail by calling =ui-e= function. *** Keeping the screen on in debug builds When you develop your application, and observe the changes on the screen, you usually don't want your device to go to sleep. Calling =(keep-screen-on this)= in the beginning of =:on-create= will ensure the screen doesn't dim out in debug build, however in release mode the macro will do nothing. ** [[http://clojure-android.github.com/neko/#neko.dialog.alert][neko.dialog.alert]] Contains a builder for AlertDialog. A single function =alert-dialog-builder= takes a map of options, and returns a AlertDialog$Builder object. Example:
(defactivity ...
  ...
 (onCreateDialog [this id _]
   (-> (alert-dialog-builder this
         {:message "Dialog message"
          :cancelable true
          :positive-text "OK"
          :positive-callback (fn [dialog res] ...)
          :negative-text "Cancel"
          :negative-callback (fn [dialog res] ...)})
       .create)))
** [[http://clojure-android.github.com/neko/#neko.find-view][neko.find-view]] This namespace contains two functions: =find-view= and =find-views= that allow to obtain references to child views from a parent view or an activity by view's =:id= attributes. Second function works just the same as the first one but it takes a variable number of view IDs and returns found views in a vector. Here is a simple example. Please notice that passing the UI tree directly to =set-content-view!= (without calling =make-ui= manually) is essential for =find-view= to work. #+BEGIN_SRC clojure (ns org.bar.baz (:require [neko.activity :refer [defactivity set-content-view!]] [neko.find-view :refer [find-view find-views]] [neko.threading :refer [on-ui]] [neko.ui :refer [config]])) (defactivity org.bar.baz.MainActivity :on-create (fn [this bundle] (on-ui (set-content-view! this [:linear-layout {} [:button {:id ::mybtn :text "A button" :on-click (fn [w] (let [edit (find-view this ::myedit)] (config edit :text "Clicked!")))}] [:edit-text {:id ::myedit}]])))) #+END_SRC And =find-views= in this example could be used like this: #+BEGIN_SRC clojure (let [[edit btn] (find-views this ::myedit ::mybtn)] ... ) #+END_SRC For more information on =:id= trait see [[https://github.com/clojure-android/neko/wiki/User-interface#list-of-most-useful-traits][Traits]] section. ** neko.intent =intent= is a function for creating Intent objects. Has two arities: - takes an action String and an extras map - takes an Activity instance, classname, and an extras map. In second arity the classname can be either a Class object, a fully qualified symbol of the class to be resolved, or a symbol starting with =.= (then the application package name will be prepended to it.
(intent a '.MainActivity {:image-id 16})
;; is the same as
(intent a 'org.my.package.MainActivity {:image-id 16})
Extras map will be saved into extras of the Intent. =put-extras= function can also be called separately to fill extras of an existing intent object. Extras map supports both string and keyword keys (keywords are converted into strings during =put-extras=, and back during =neko.data/like-map=). ** neko.listeners Subnamespaces in this namespace provide different utilities to create event listeners. Every listener function takes a callback function as its argument and returns corresponding Listener object. Later you can attach the returned object to the UI element using necessary methods. Functional versions of listeners have =-call= suffix. The number of arguments a callback function should accept for every event listener can be found in docstrings for the listeners. Every listener is also available in macro version (without the =-call= suffix that takes body to execute as argument. It also establishes implicit arguments in the lexical scope. You can find arguments' names in docstrings for listeners. For example, here are two identical declarations: #+BEGIN_SRC clojure (.setOnClickListener ok-button (on-click-call (fn [view] (toast (str "View clicked: " view) :long)))) (.setOnClickListener ok-button (on-click (toast (str "View clicked: " view) ;; "view" is implicit :long))) #+END_SRC Many listeners have respective traits that use them, for instance: : [:button {:on-click (fn [v] ... )}] *** [[http://clojure-android.github.com/neko/#neko.listeners.view][neko.listeners.view]] Uility functions and macros for setting listeners corresponding to the android.view.View class. List of listeners in this namespace include: - on-click - on-create-context-menu - on-drag - on-focus-change - on-key - on-long-click - on-touch *** [[http://clojure-android.github.com/neko/#neko.listeners.text-view][neko.listeners.text-view]] Uility functions and macros for creating listeners corresponding to the android.widget.TextView class. List of listeners in this namespace include: - on-editor-action *** [[http://clojure-android.github.com/neko/#neko.listeners.adapter-view][neko.listeners.adapter-view]] Uility functions and macros for creating listeners corresponding to the android.widget.AdapterView class. List of listeners in this namespace include: - on-item-click - on-item-long-click - on-item-selected *** [[http://clojure-android.github.com/neko/#neko.listeners.dialog][neko.listeners.dialog]] Uility functions and macros for setting listeners corresponding to the android.content DialogInterface interface. List of listeners in this namespace include: - on-cancel - on-click - on-dismiss - on-key - on-multi-choice-click ** [[http://clojure-android.github.com/neko/#neko.log][neko.log]] Contains logging macros that wrap =android.util.Log=. For detailed information see [[https://github.com/clojure-android/neko/wiki/Logging#nekolog][Logging]] page. ** [[http://clojure-android.github.com/neko/#neko.notify][neko.notify]] Provides convenient wrappers for Toast and Notification APIs. *** Toasts To show user a Toast do the following: #+begin_src clojure (toast context "My message" :long) #+end_src First argument is any Context object, second is a message, third is toast duration (could be either =:long= or =:short=). Duration argument can be omitted. Note that unlike in Java API =toast= function creates a toast and immediately shows it. If for some reason you need to create a reusable Toast, feel free to use Toast constructor and then call =.show= on it. *** Notifications To create a Notification object use =notification= function. You have to provide the following arguments to it: - icon (optional if the default icon is set) - ticker-text - content-title - content-text - action - when (*now* by default) Action should be in the form of vector where the first element is a PendingIntent type (=:activity=, =:broadcast=, =:service=) and the second one is an action to create Intent from. You can set the default notification icon by calling =set-default-notification-icon!= that takes one argument - either an actual image resource or a Android resource ID. To show the created notification call =fire= on it. Two-argument version takes an ID (either integer or keyword) as the first argument that allows to =cancel= the notification in future. #+begin_src clojure (fire :new-mail (notification {:icon R$drawable/ic_launcher :ticker-text "You've got mail" :content-title "One new message" :content-text "FROM: foo@bar.com" :action [:activity "my.package.VIEW_MAIL"]})) (cancel :new-mail) #+end_src ** neko.resource *** Import application resources Same as in original Android, you can access any resource via Java interop, like =android.R$drawable/ic_menu_add= or =org.my.app.R$string/app_name=. But it is certainly inconvenient to specify full package name for your application resources. To avoid this you can put =(neko.resource/import-all)= call at the beginning of your namespace (under =ns= declaration). This will import all R subclasses, like =R$drawable=, =R$string= etc. so that you can drop the package name when using them. *** Getting resource in runtime =get-string= and =get-drawable= function return actual String and Drawable objects given a resources ID. If =get-string= is provided with two or more arguments, it treats the first argument as a format, and the rest arguments as substitutions.
(get-string R$string/app_name) ;=> returns the application name
(get-drawable R$drawable/ic_launcher) ;=> returns the application icon
** [[http://clojure-android.github.com/neko/#neko.threading][neko.threading]] Utilities used to manage multiple threads on Android. *** Operating on UI thread Any code that touches the user interface has to be run on the application UI thread. Neko provides a macro called =on-ui= that takes arbitrary code to be run it on the main UI thread. : (on-ui : (.setText ok-button "OK")) If the current thread is already the UI one, then the code will be directly executed. Code inside =on-ui= is automatically wrapped in =neko.debug/safe-for-ui=, so if the exception happened on UI thread during development it won't crash the application. Functional version =on-ui*= wraps a given nullary function into =(on-ui)= and returns it as a new function (so you have to call it by yourself). One more useful function is =on-ui-thread?= which tells whether the thread it is executed on is the UI one. *** Posting code on View's message queue Alternatively you can add code on the message queue of a specific View object you'd like this code to operate on. =post= macro is similar to =on-ui= but additionally takes a View object as first argument. : (post ok-button : (.setText ok-button "OK")) There is also =post-delayed= macro that takes additional time argument in milliseconds, and executes its body after this time passes. : (post-delayed ok-button 3000 ;; Wait for 3 seconds : (.setText ok-button "OK")) ** [[http://clojure-android.github.com/neko/#neko.ui][neko.ui]] Tools for defining and manipulating Android UI elements. See [[https://github.com/clojure-android/neko/wiki/User-interface][User interface]] page for detailed instructions. The most important thing here is =make-ui= function. It allows to declaratively define the UI of your application. This function is intended as a replacement for XML-defined user interface. =make-ui= returns a View. Usually you don't have to call =make-ui= manually as in most places you can pass UI tree directly (in =set-content-view!=, in adapters' =new-view-fn= etc.). *** Building a UI tree =make-ui= takes an activity context and a UI tree as arguments. The tree is a vector that contains of these elements: - element keyword - attribute map - & other elements #+begin_src clojure (make-ui this [:linear-layout {:orientation :vertical} [:button {:text "A button" :enabled true}]]) #+end_src The element keyword represents the element you want to create. Thus =:button= stands for android.widget.Button, =:linear-layout= --- for android.widget.LinearLayout and so on. All elements are defined in the *neko.ui.mapping* namespace and new elements can be added. *** Attributes The attribute map consists of key-value pairs where keys are Clojure keywords. By default attributes are processed in such fashion that these pairs are trasformed into setter calls. So for instance, =:editable false= is transformed into =(.setEditable edit-wdg false)=. For non-standard attributes the so called *traits* can be defined. Trait is a function that takes an attribute map and performs some actions for the attribute(s) it represents. All traits of the element are applied to the attribute map before the default handler kicks in. Every element has its own traits list. In the following example a special *on-click* trait will take specified anonymous function, wrap it in OnClickListener and then generate call to =.setOnClickListener=. : (make-ui [:button {:on-click (fn [w] (toast "Clicked!"))}]) Attribute values are also treated specially. If value is a Clojure keyword, then it is looked up in the element's value map. This map contains a mapping of element-specific keywords to real values. If the keyword is not present there, it is transformed into a static field following a rule: all letters are uppercased, and dashes are replaced with with underscores. For example, the value =:choice-mode-multiple= defined for the =:list-view= element will be transformed into =ListView/CHOICE_MODE_MULTIPLE=. *** Changing element after it is created You can use =config= function to change existing element's state. It works similarly to =make-ui=, but receives attributes as optional arguments rather than in one single map. #+begin_src clojure (config ok-button :text "OK" :on-click (fn [_] (execute-operation))) #+end_src *** Utilities =get-screen-orientation= returns a keyword for the current orientation of the device. Can return =:portrait=, =:landscape=, =:square=, or =:undefined= (rare case which means something is wrong). ** [[http://clojure-android.github.com/neko/#neko.ui.mapping][neko.ui.mapping]] This namespace stores the keywords-to-elements mapping and provides utilities to define your own elements. *** Define a new element You can create new element using =defelement= macro. The first argument it takes is the keyword name of the element. Other (optional) arguments: - classname --- which class the element represents (if any) - traits --- the list of traits for this element - attributes --- a map of default attributes for this element - values --- a map of specific attribute values - inherits --- see below - container-type --- see below. #+begin_src clojure (defelement :text-view :classname android.widget.TextView :traits [:id :layout-params] :attributes {:text :default-text} :values {:default-text "I am a textview"}) #+end_src *** Define an element based on an existing one You also can define an element that inherits a base one. It is achieved by providing =:inherits= option to the =defelement=. Values and attributes maps provided are merged with the original ones (the newer rewrite the older), provided traits are appended to the original. #+begin_src clojure (defelement :long-thin-button :inherits :button :attributes {:layout-width :fill :layout-height :wrap}) #+end_src If you want to inherit from a container element (like =:linear-layout= or =:relative-layout=) and you don't take control over the attributes they expect (like =:layout-width= or =:layout-above= ** [[http://clojure-android.github.com/neko/#neko.ui.listview][neko.ui.listview]] This namespace contains helper functions to manipulate ListViews. Currently it has only two functions: =get-checked= and =set-checked!=, both of them operate on ListViews with multiple check items enabled. =get-checked= takes a ListView instance and returns a vector of numbers. These numbers represent the numbers of those items in the list that are checked. Two-argument version takes a ListView and an arbitrary sequence (usually the one from which ListView adapter was constructed) and returns only those elements that are checked. Be careful to provide a sequence not exceeding the number of ListView elements itself. =set-checked!= takes a ListView and a sequence of numbers and sets the respective ListView items to be checked. ** [[http://clojure-android.github.com/neko/#neko.ui.adapters][neko.ui.adapters]] This namespace provides custom adapters for ListView, GridView etc. *** ref-adapter =ref-adapter= function creates an Adapter that watches over a reference type and updates itself when the reference is updated. =ref-adapter= takes three arguments: - =create-view-fn= --- function of context that either returns an UI tree or a new View instance that acts as single ListView item; - =update-view-fn= --- function that takes four arguments: item's position in the ListView, View instance of the item, parent container and the data for the current item. The function should update the View instance with the provided data; - =ref-type= --- a ref or an atom that stores data; - =access-fn= (optional) --- function that is called on the dereferenced =ref-type= to get the list that should be displayed by ListView. By default =identity= function is used. ref-adapter implements View caching technique. If View for the element has not been created yet, =create-view-fn= is called to create it. Then =update-view-fn= is called on the View with data provided. =access-fn= allows a reference type to store some broader data structure (a map, for example) and to display only part of it in a ListView. When the reference type is updated, adapter updates automatically. The following example demonstrates usage of ref-adapter along with ListView: #+begin_src clojure (def alphabet (atom {:type :phonetic :letters ["alpha" "bravo" "charlie" "delta"]})) (defn make-adapter [] (ref-adapter (fn [_] [:linear-layout {:id-holder true} [:text-view {:id ::caption-tv}]]) (fn [position view _ data] (let [tv (find-view view ::caption-tv)] (config tv :text (str position ". " )))) alphabet :letters)) ;; Somewhere in Activity.onCreate() ... (set-content-view! this [:list-view {:adapter (make-adapter)}]) ;; Now the created ListView displays four items: ;; 1. alpha ;; 2. bravo ;; 3. charlie ;; 4. delta (swap! alphabet update-in [:letters] conj "echo") ;; ListView automatically appended another item: 5. echo #+end_src Please keep in mind, that if you want to manually create a View instance in create-fn (rather than return a UI tree), you have to call =make-ui-element= with additional parameters instead of =make-ui=. This is important because ListView expects special kind of LayoutParams to be set for the widget. =make-ui-element= takes three obligatory arguments - an Activity context, UI tree and the options map. #+begin_src clojure (defn make-adapter [activity] (ref-adapter (fn [] (neko.ui/make-ui-element activity [:text-view {}] {:container-type :abs-listview-layout})) (fn [position view _ data] (.setText ^TextView view (str position ". " data))) alphabet :letters)) #+end_src *** cursor-adapter =cursor-adapter= creates a special CursorAdapter instance that synergizes with =neko.data.sqlite= namespace. It takes the following arguments: - =context= --- Activity instance - =create-view-fn= --- nullary function that either returns an UI tree or a new View instance that acts as single AdapterView item - =update-view-fn= --- function that takes three arguments: View to be updated, cursor and the already extracted data map for the current item. The function should update the View instance with the provided data. - =cursor-or-cursor-fn= --- this can be either cursor object returned by =neko.data.sqlite/query=, or a nullary function that returns such cursor when called. Unlike ref-adapter, you have to update cursor-adapter manually by using =update-cursor= function. It takes single argument --- the adapter --- if the latter was created with =cursor-fn=, or adapter and new cursor if the adapter was created by passing a cursor. #+BEGIN_SRC clojure (defn get-my-cursor [options] (neko.data.sqlite/query ... options ...)) (defn make-adapter [activity] (neko.ui.adapters/cursor-adapter activity (fn [] [:linear-layout {:id-holder true} [:text-view {:id ::caption-tv}]]) (fn [view _ data] (let [tv (find-view view ::caption-tv)] (config tv :text (:first-name data)))) (fn [] (get-my-cursor (options-from-somewhere))))) ;; We passed cursor-fn ;; Somewhere in Activity.onCreate() ... (set-content-view! this [:list-view {:id ::my-lv :adapter (make-adapter this)}]) ;; Somewhere in a place you want to update ListView (let [^ListView lv (find-view activity-context ::my-lv)] (neko.ui.adapters/update-cursor (.getAdapter lv))) ;; So we call update-cursor with 1 argument #+END_SRC
*Namespaces* - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekoaction-bar][neko.action-bar]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekoactivity][neko.activity]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekocontext][neko.context]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekodata][neko.data]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#nekodatashared-prefs][neko.data.shared-prefs]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekodebug][neko.debug]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#nekodialogalert][neko.dialog.alert]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekofind-view][neko.find-view]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#nekointent][neko.intent]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekolisteners][neko.listeners]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekolog][neko.log]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekonotify][neko.notify]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekoresource][neko.resource]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekothreading][neko.threading]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekoui][neko.ui]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekouimapping][neko.ui.mapping]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekouilistview][neko.ui.listview]] - [[https://github.com/clojure-android/neko/wiki/Namespaces#wiki-nekouiadapters][neko.ui.adapters]] *User interface* - [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-introduction][Intro]] - [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-using-nekoui][Using neko.ui]] + [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-attributes][Attributes]] + [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-traits][Traits]] - [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-extending-nekoui][Extending neko.ui]] + [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-defining-new-elements][Custom elements]] + [[https://github.com/clojure-android/neko/wiki/User-interface#wiki-creating-new-traits][Custom traits]] *Action bar* - [[https://github.com/clojure-android/neko/wiki/Action-bar#wiki-create-simple-action-bar][Simple action bar]] - [[https://github.com/clojure-android/neko/wiki/Action-bar#wiki-supported-attributes][Attributes]] - [[https://github.com/clojure-android/neko/wiki/Action-bar#wiki-action-bar-tabs][Tabbed action bar]] *SQLite* - [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite#wiki-define-a-schema][Defining a schema]] - [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite#wiki-get-database][Getting the database]] - [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite#wiki-sql-operations][SQL operations]] + [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite#wiki-insert-data][INSERT]] + [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite#wiki-update-data][UPDATE]] + [[https://github.com/clojure-android/neko/wiki/Working-with-SQLite#wiki-retrieve-data][SELECT]] *Logging* - [[https://github.com/clojure-android/neko/wiki/Logging#nekolog][neko.log]] - [[https://github.com/clojure-android/neko/wiki/Logging#clojuretoolslogging][clojure.tools.logging]]

Clone this wiki locally