This repository was archived by the owner on Apr 25, 2024. It is now read-only.
forked from sattvik/neko
-
Notifications
You must be signed in to change notification settings - Fork 36
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.
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:
** [[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.
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.
** [[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
(defpreferences prefs "my_sp_file")
(swap! prefs assoc :user "dummy")
;; Later, application is restarted
(:user @prefs)
;=> "dummy"(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)))(intent a '.MainActivity {:image-id 16})
;; is the same as
(intent a 'org.my.package.MainActivity {:image-id 16})(get-string R$string/app_name) ;=> returns the application name
(get-drawable R$drawable/ic_launcher) ;=> returns the application icon
*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]]