{"action":"created","comment":{"url":"https://api.github.com/repos/facebook/react-native/pulls/comments/56380595","id":56380595,"diff_hunk":"@@ -0,0 +1,81 @@\n+/**\n+ * Copyright (c) 2015-present, Facebook, Inc.\n+ * All rights reserved.\n+ *\n+ * This source code is licensed under the BSD-style license found in the\n+ * LICENSE file in the root directory of this source tree. An additional grant\n+ * of patent rights can be found in the PATENTS file in the same directory.\n+ */\n+\n+package com.facebook.react.uimanager.animation;\n+\n+import com.facebook.infer.annotation.Assertions;\n+import com.facebook.react.bridge.JavaOnlyMap;\n+\n+import java.util.ArrayList;\n+import java.util.List;\n+\n+import javax.annotation.Nullable;\n+\n+/**\n+ * Base class for all Animated.js library node types that can be created on the \"native\" side.\n+ */\n+/*package*/ class AnimatedNode {\n+\n+  private static final int DEFAULT_ANIMATED_NODE_CHILD_COUNT = 1;\n+  /*package*/ static final int INITIAL_DFS_COLOR = 0;\n+\n+  /*package*/ @Nullable List<AnimatedNode> mChildren; /* lazy-initialized when a child is added */","path":"ReactAndroid/src/main/java/com/facebook/react/uimanager/animation/AnimatedNode.java","position":28,"original_position":28,"commit_id":"2ae5b7f732f460166b509f262e0458c6abdac083","original_commit_id":"2ae5b7f732f460166b509f262e0458c6abdac083","user":{"login":"astreet","id":594924,"avatar_url":"https://avatars.githubusercontent.com/u/594924?v=3","gravatar_id":"","url":"https://api.github.com/users/astreet","html_url":"https://github.com/astreet","followers_url":"https://api.github.com/users/astreet/followers","following_url":"https://api.github.com/users/astreet/following{/other_user}","gists_url":"https://api.github.com/users/astreet/gists{/gist_id}","starred_url":"https://api.github.com/users/astreet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/astreet/subscriptions","organizations_url":"https://api.github.com/users/astreet/orgs","repos_url":"https://api.github.com/users/astreet/repos","events_url":"https://api.github.com/users/astreet/events{/privacy}","received_events_url":"https://api.github.com/users/astreet/received_events","type":"User","site_admin":false},"body":"... we should probably be doing this in CSSNode","created_at":"2016-03-16T17:38:06Z","updated_at":"2016-03-16T17:38:06Z","html_url":"https://github.com/facebook/react-native/pull/6466#discussion_r56380595","pull_request_url":"https://api.github.com/repos/facebook/react-native/pulls/6466","_links":{"self":{"href":"https://api.github.com/repos/facebook/react-native/pulls/comments/56380595"},"html":{"href":"https://github.com/facebook/react-native/pull/6466#discussion_r56380595"},"pull_request":{"href":"https://api.github.com/repos/facebook/react-native/pulls/6466"}}},"pull_request":{"url":"https://api.github.com/repos/facebook/react-native/pulls/6466","id":62898025,"html_url":"https://github.com/facebook/react-native/pull/6466","diff_url":"https://github.com/facebook/react-native/pull/6466.diff","patch_url":"https://github.com/facebook/react-native/pull/6466.patch","issue_url":"https://api.github.com/repos/facebook/react-native/issues/6466","number":6466,"state":"open","locked":false,"title":"Execute Animated.js declarative animation on UIThread on Android.","user":{"login":"kmagiera","id":726445,"avatar_url":"https://avatars.githubusercontent.com/u/726445?v=3","gravatar_id":"","url":"https://api.github.com/users/kmagiera","html_url":"https://github.com/kmagiera","followers_url":"https://api.github.com/users/kmagiera/followers","following_url":"https://api.github.com/users/kmagiera/following{/other_user}","gists_url":"https://api.github.com/users/kmagiera/gists{/gist_id}","starred_url":"https://api.github.com/users/kmagiera/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmagiera/subscriptions","organizations_url":"https://api.github.com/users/kmagiera/orgs","repos_url":"https://api.github.com/users/kmagiera/repos","events_url":"https://api.github.com/users/kmagiera/events{/privacy}","received_events_url":"https://api.github.com/users/kmagiera/received_events","type":"User","site_admin":false},"body":"This is the first from the series of PRs I'm going to be sending shorty that would let Animated.js animations to run off the JS thread (for Android only).\r\n\r\n\r\nThis PR introduce a new native module that will be used for offloading animations - NativeAnimatedModule. It has a simple API that allows for animated nodes management via methods like: create/drop animated node, connect/disconnect nodes, start animation of a value node, attach/detach animated from a native view.\r\n\r\n\r\nSimilarly to how we handle UIManager view hierarchy updates we create a queue of animated graph operations that are then executed on the UI thread. This isolates us from problems that may be caused by concurrent updates of animated graph while UI thread is \"executing\" the animation.\r\n\r\n\r\nThe most important class NativeAnimatedNodesManager.java implements a management interface for animated nodes graph as well as implements a graph traversal algorithm that is run for each animation frame. For each animation frame we visit animated nodes that might've been updated as well as their children that may use parent's values to update themselves. At the end of the traversal algorithm we expect to reach a special type of the node: PropsAnimatedNode that is then responsible for calculating property map which can be sent to native view hierarchy to update the view.\r\n\r\n\r\nFrom the \"client\" perspective the API is as simple as adding: `useNativeDriver: true` to the set of animation properties, e.g:\r\n```\r\nAnimated.timing(\r\n  this.state.fadeAnim,\r\n  {\r\n    toValue: 1,\r\n    duration: 2000,\r\n    useNativeDriver: true,\r\n  },\r\n).start();\r\n```\r\n\r\n\r\nThis approach doesn't let us support animating layout properties as it updates the values directly on the native view hierarchy. In order to be able to handle updates of layout props we'd need to run the updates on shadow view hierarchy first (on \"native\" thread). However a lot of this code could be reused if we decided to implement support for layout props (my initial prototype was capable of updating layout props off the JS thread).\r\n\r\n\r\nThis PR adds support only for a limited number of Animated.js library features (mainly to keep it shorter), here is what's supported as of this PR:\r\n - Works only for android\r\n - Only one type of animation: Animated.timing\r\n - One can use animated values only for non-layout, numeric properties (e.g. support for transform property is disabled)\r\n - One can use JS driven version of Animated.js library along with \"native\" animated. The only limitation is that we cannot drive same value both by native and JS animated driver.\r\n\r\n\r\nWhat's coming up next (have most of the work done but will be sending this later to keep this change as simple as possible):\r\n - More animation types: decay, spring\r\n - Support for transform property\r\n - Support for \"operation\" nodes: Animated.add, Animated.multiply, etc.\r\n - Animated.event support\r\n - Unit tests for the graph traversal algorithm\r\n\r\n\r\n**IMPORTANT**: This PR doesn't enable animated native module by default. In order to use it you'd need to add `NativeAnimatedModule` to the list of yours app 'packages'\r\n\r\n\r\n**Test plan**\r\n 1. Add `NativeAnimatedModule` to the list of native modules for you app\r\n 2. Add `useNativeDriver: true` to your animation config (Animated.timing only for now). You can use my example app: https://gist.github.com/kmagiera/bbfbac6c00077d188bc5\r\n 3. Enable SPY_MODE in MessageQueue.js to see that setNativeProps operation are no longer passed over the bridge while animation is running and `useNativeDriver` is set to `true`.","created_at":"2016-03-15T12:31:24Z","updated_at":"2016-03-16T17:38:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1a912677bfc35c94cb9ad78caff52b973cc03750","assignee":{"login":"astreet","id":594924,"avatar_url":"https://avatars.githubusercontent.com/u/594924?v=3","gravatar_id":"","url":"https://api.github.com/users/astreet","html_url":"https://github.com/astreet","followers_url":"https://api.github.com/users/astreet/followers","following_url":"https://api.github.com/users/astreet/following{/other_user}","gists_url":"https://api.github.com/users/astreet/gists{/gist_id}","starred_url":"https://api.github.com/users/astreet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/astreet/subscriptions","organizations_url":"https://api.github.com/users/astreet/orgs","repos_url":"https://api.github.com/users/astreet/repos","events_url":"https://api.github.com/users/astreet/events{/privacy}","received_events_url":"https://api.github.com/users/astreet/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/facebook/react-native/pulls/6466/commits","review_comments_url":"https://api.github.com/repos/facebook/react-native/pulls/6466/comments","review_comment_url":"https://api.github.com/repos/facebook/react-native/pulls/comments{/number}","comments_url":"https://api.github.com/repos/facebook/react-native/issues/6466/comments","statuses_url":"https://api.github.com/repos/facebook/react-native/statuses/2ae5b7f732f460166b509f262e0458c6abdac083","head":{"label":"kmagiera:offload_animated_clean","ref":"offload_animated_clean","sha":"2ae5b7f732f460166b509f262e0458c6abdac083","user":{"login":"kmagiera","id":726445,"avatar_url":"https://avatars.githubusercontent.com/u/726445?v=3","gravatar_id":"","url":"https://api.github.com/users/kmagiera","html_url":"https://github.com/kmagiera","followers_url":"https://api.github.com/users/kmagiera/followers","following_url":"https://api.github.com/users/kmagiera/following{/other_user}","gists_url":"https://api.github.com/users/kmagiera/gists{/gist_id}","starred_url":"https://api.github.com/users/kmagiera/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmagiera/subscriptions","organizations_url":"https://api.github.com/users/kmagiera/orgs","repos_url":"https://api.github.com/users/kmagiera/repos","events_url":"https://api.github.com/users/kmagiera/events{/privacy}","received_events_url":"https://api.github.com/users/kmagiera/received_events","type":"User","site_admin":false},"repo":{"id":46790775,"name":"react-native","full_name":"kmagiera/react-native","owner":{"login":"kmagiera","id":726445,"avatar_url":"https://avatars.githubusercontent.com/u/726445?v=3","gravatar_id":"","url":"https://api.github.com/users/kmagiera","html_url":"https://github.com/kmagiera","followers_url":"https://api.github.com/users/kmagiera/followers","following_url":"https://api.github.com/users/kmagiera/following{/other_user}","gists_url":"https://api.github.com/users/kmagiera/gists{/gist_id}","starred_url":"https://api.github.com/users/kmagiera/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmagiera/subscriptions","organizations_url":"https://api.github.com/users/kmagiera/orgs","repos_url":"https://api.github.com/users/kmagiera/repos","events_url":"https://api.github.com/users/kmagiera/events{/privacy}","received_events_url":"https://api.github.com/users/kmagiera/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kmagiera/react-native","description":"A framework for building native apps with React.","fork":true,"url":"https://api.github.com/repos/kmagiera/react-native","forks_url":"https://api.github.com/repos/kmagiera/react-native/forks","keys_url":"https://api.github.com/repos/kmagiera/react-native/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kmagiera/react-native/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kmagiera/react-native/teams","hooks_url":"https://api.github.com/repos/kmagiera/react-native/hooks","issue_events_url":"https://api.github.com/repos/kmagiera/react-native/issues/events{/number}","events_url":"https://api.github.com/repos/kmagiera/react-native/events","assignees_url":"https://api.github.com/repos/kmagiera/react-native/assignees{/user}","branches_url":"https://api.github.com/repos/kmagiera/react-native/branches{/branch}","tags_url":"https://api.github.com/repos/kmagiera/react-native/tags","blobs_url":"https://api.github.com/repos/kmagiera/react-native/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kmagiera/react-native/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kmagiera/react-native/git/refs{/sha}","trees_url":"https://api.github.com/repos/kmagiera/react-native/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kmagiera/react-native/statuses/{sha}","languages_url":"https://api.github.com/repos/kmagiera/react-native/languages","stargazers_url":"https://api.github.com/repos/kmagiera/react-native/stargazers","contributors_url":"https://api.github.com/repos/kmagiera/react-native/contributors","subscribers_url":"https://api.github.com/repos/kmagiera/react-native/subscribers","subscription_url":"https://api.github.com/repos/kmagiera/react-native/subscription","commits_url":"https://api.github.com/repos/kmagiera/react-native/commits{/sha}","git_commits_url":"https://api.github.com/repos/kmagiera/react-native/git/commits{/sha}","comments_url":"https://api.github.com/repos/kmagiera/react-native/comments{/number}","issue_comment_url":"https://api.github.com/repos/kmagiera/react-native/issues/comments{/number}","contents_url":"https://api.github.com/repos/kmagiera/react-native/contents/{+path}","compare_url":"https://api.github.com/repos/kmagiera/react-native/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kmagiera/react-native/merges","archive_url":"https://api.github.com/repos/kmagiera/react-native/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kmagiera/react-native/downloads","issues_url":"https://api.github.com/repos/kmagiera/react-native/issues{/number}","pulls_url":"https://api.github.com/repos/kmagiera/react-native/pulls{/number}","milestones_url":"https://api.github.com/repos/kmagiera/react-native/milestones{/number}","notifications_url":"https://api.github.com/repos/kmagiera/react-native/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kmagiera/react-native/labels{/name}","releases_url":"https://api.github.com/repos/kmagiera/react-native/releases{/id}","deployments_url":"https://api.github.com/repos/kmagiera/react-native/deployments","created_at":"2015-11-24T12:39:08Z","updated_at":"2016-03-02T16:42:14Z","pushed_at":"2016-03-16T08:14:57Z","git_url":"git://github.com/kmagiera/react-native.git","ssh_url":"git@github.com:kmagiera/react-native.git","clone_url":"https://github.com/kmagiera/react-native.git","svn_url":"https://github.com/kmagiera/react-native","homepage":"http://facebook.github.io/react-native/","size":40110,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":2,"default_branch":"master"}},"base":{"label":"facebook:master","ref":"master","sha":"2209131933a94a805238517d55baa32310ac0a39","user":{"login":"facebook","id":69631,"avatar_url":"https://avatars.githubusercontent.com/u/69631?v=3","gravatar_id":"","url":"https://api.github.com/users/facebook","html_url":"https://github.com/facebook","followers_url":"https://api.github.com/users/facebook/followers","following_url":"https://api.github.com/users/facebook/following{/other_user}","gists_url":"https://api.github.com/users/facebook/gists{/gist_id}","starred_url":"https://api.github.com/users/facebook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facebook/subscriptions","organizations_url":"https://api.github.com/users/facebook/orgs","repos_url":"https://api.github.com/users/facebook/repos","events_url":"https://api.github.com/users/facebook/events{/privacy}","received_events_url":"https://api.github.com/users/facebook/received_events","type":"Organization","site_admin":false},"repo":{"id":29028775,"name":"react-native","full_name":"facebook/react-native","owner":{"login":"facebook","id":69631,"avatar_url":"https://avatars.githubusercontent.com/u/69631?v=3","gravatar_id":"","url":"https://api.github.com/users/facebook","html_url":"https://github.com/facebook","followers_url":"https://api.github.com/users/facebook/followers","following_url":"https://api.github.com/users/facebook/following{/other_user}","gists_url":"https://api.github.com/users/facebook/gists{/gist_id}","starred_url":"https://api.github.com/users/facebook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facebook/subscriptions","organizations_url":"https://api.github.com/users/facebook/orgs","repos_url":"https://api.github.com/users/facebook/repos","events_url":"https://api.github.com/users/facebook/events{/privacy}","received_events_url":"https://api.github.com/users/facebook/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/facebook/react-native","description":"A framework for building native apps with React.","fork":false,"url":"https://api.github.com/repos/facebook/react-native","forks_url":"https://api.github.com/repos/facebook/react-native/forks","keys_url":"https://api.github.com/repos/facebook/react-native/keys{/key_id}","collaborators_url":"https://api.github.com/repos/facebook/react-native/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/facebook/react-native/teams","hooks_url":"https://api.github.com/repos/facebook/react-native/hooks","issue_events_url":"https://api.github.com/repos/facebook/react-native/issues/events{/number}","events_url":"https://api.github.com/repos/facebook/react-native/events","assignees_url":"https://api.github.com/repos/facebook/react-native/assignees{/user}","branches_url":"https://api.github.com/repos/facebook/react-native/branches{/branch}","tags_url":"https://api.github.com/repos/facebook/react-native/tags","blobs_url":"https://api.github.com/repos/facebook/react-native/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/facebook/react-native/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/facebook/react-native/git/refs{/sha}","trees_url":"https://api.github.com/repos/facebook/react-native/git/trees{/sha}","statuses_url":"https://api.github.com/repos/facebook/react-native/statuses/{sha}","languages_url":"https://api.github.com/repos/facebook/react-native/languages","stargazers_url":"https://api.github.com/repos/facebook/react-native/stargazers","contributors_url":"https://api.github.com/repos/facebook/react-native/contributors","subscribers_url":"https://api.github.com/repos/facebook/react-native/subscribers","subscription_url":"https://api.github.com/repos/facebook/react-native/subscription","commits_url":"https://api.github.com/repos/facebook/react-native/commits{/sha}","git_commits_url":"https://api.github.com/repos/facebook/react-native/git/commits{/sha}","comments_url":"https://api.github.com/repos/facebook/react-native/comments{/number}","issue_comment_url":"https://api.github.com/repos/facebook/react-native/issues/comments{/number}","contents_url":"https://api.github.com/repos/facebook/react-native/contents/{+path}","compare_url":"https://api.github.com/repos/facebook/react-native/compare/{base}...{head}","merges_url":"https://api.github.com/repos/facebook/react-native/merges","archive_url":"https://api.github.com/repos/facebook/react-native/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/facebook/react-native/downloads","issues_url":"https://api.github.com/repos/facebook/react-native/issues{/number}","pulls_url":"https://api.github.com/repos/facebook/react-native/pulls{/number}","milestones_url":"https://api.github.com/repos/facebook/react-native/milestones{/number}","notifications_url":"https://api.github.com/repos/facebook/react-native/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/facebook/react-native/labels{/name}","releases_url":"https://api.github.com/repos/facebook/react-native/releases{/id}","deployments_url":"https://api.github.com/repos/facebook/react-native/deployments","created_at":"2015-01-09T18:10:16Z","updated_at":"2016-03-16T17:00:51Z","pushed_at":"2016-03-16T17:35:29Z","git_url":"git://github.com/facebook/react-native.git","ssh_url":"git@github.com:facebook/react-native.git","clone_url":"https://github.com/facebook/react-native.git","svn_url":"https://github.com/facebook/react-native","homepage":"http://facebook.github.io/react-native/","size":83300,"stargazers_count":28791,"watchers_count":28791,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":5468,"mirror_url":null,"open_issues_count":1019,"forks":5468,"open_issues":1019,"watchers":28791,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/facebook/react-native/pulls/6466"},"html":{"href":"https://github.com/facebook/react-native/pull/6466"},"issue":{"href":"https://api.github.com/repos/facebook/react-native/issues/6466"},"comments":{"href":"https://api.github.com/repos/facebook/react-native/issues/6466/comments"},"review_comments":{"href":"https://api.github.com/repos/facebook/react-native/pulls/6466/comments"},"review_comment":{"href":"https://api.github.com/repos/facebook/react-native/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/facebook/react-native/pulls/6466/commits"},"statuses":{"href":"https://api.github.com/repos/facebook/react-native/statuses/2ae5b7f732f460166b509f262e0458c6abdac083"}}}}