Created
May 22, 2017 02:51
-
-
Save monzee/976393c8097c2496d701109fdcba491f to your computer and use it in GitHub Desktop.
Java vs. Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MainActivity extends AppCompatActivity { | |
static class Retained { | |
final LipsumAdapter adapter = new LipsumAdapter(); | |
State loadState = State.Case::unknown; | |
} | |
interface State { | |
void match(Case of); | |
interface Case { | |
void unknown(); | |
void loading(Future<State> result); | |
void loaded(List<String> items); | |
void failed(Exception error); | |
} | |
} | |
static class LipsumAdapter extends RecyclerView.Adapter<LipsumAdapter.RowView> { | |
static class RowView extends RecyclerView.ViewHolder { | |
final TextView root; | |
RowView(View itemView) { | |
super(itemView); | |
itemView.setClickable(true); | |
root = (TextView) itemView; | |
} | |
void show(String item) { | |
root.setText(item); | |
} | |
} | |
private List<String> items; | |
@Override | |
public RowView onCreateViewHolder(ViewGroup parent, int viewType) { | |
return new RowView(LayoutInflater | |
.from(parent.getContext()) | |
.inflate(android.R.layout.simple_selectable_list_item, parent, false)); | |
} | |
@Override | |
public void onBindViewHolder(RowView holder, int position) { | |
holder.show(items.get(position)); | |
} | |
@Override | |
public int getItemCount() { | |
return items.size(); | |
} | |
public void setItems(List<String> items) { | |
this.items = items; | |
notifyDataSetChanged(); | |
} | |
} | |
private static final ExecutorService BACKGROUND = Executors.newCachedThreadPool(); | |
private Retained scope; | |
private RecyclerView theItems; | |
private ProgressBar theSpinner; | |
private Future<?> waiting; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
scope = (Retained) getLastCustomNonConfigurationInstance(); | |
if (scope == null) { | |
scope = new Retained(); | |
} | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
theSpinner = (ProgressBar) findViewById(R.id.the_spinner); | |
theItems = (RecyclerView) findViewById(R.id.the_items); | |
theItems.setAdapter(scope.adapter); | |
theItems.setLayoutManager(new LinearLayoutManager(this)); | |
} | |
@Override | |
public Object onRetainCustomNonConfigurationInstance() { | |
return scope; | |
} | |
@Override | |
protected void onResume() { | |
super.onResume(); | |
update(); | |
} | |
@Override | |
protected void onPause() { | |
super.onPause(); | |
if (waiting != null) { | |
waiting.cancel(true); | |
waiting = null; | |
} | |
} | |
void update(State newState) { | |
scope.loadState = newState; | |
update(); | |
} | |
void update() { | |
scope.loadState.match(new State.Case() { | |
@Override | |
public void unknown() { | |
Future<State> result = BACKGROUND.submit(MainActivity::loadData); | |
update(of -> of.loading(result)); | |
} | |
@Override | |
public void loading(Future<State> result) { | |
showProgress(true); | |
waiting = BACKGROUND.submit(() -> { | |
State nextState = scope.loadState; | |
try { | |
nextState = result.get(); | |
} catch (ExecutionException e) { | |
nextState = of -> of.failed(e); | |
} catch (InterruptedException e) { | |
runOnUiThread(() -> Toast | |
.makeText(getApplicationContext(), "wait cancelled", Toast.LENGTH_SHORT) | |
.show()); | |
} finally { | |
State newState = nextState; | |
runOnUiThread(() -> update(newState)); | |
} | |
}); | |
} | |
@Override | |
public void loaded(List<String> items) { | |
showProgress(false); | |
waiting = null; | |
scope.adapter.setItems(items); | |
} | |
@Override | |
public void failed(Exception error) { | |
throw new RuntimeException(error); | |
} | |
}); | |
} | |
void showProgress(boolean busy) { | |
if (busy) { | |
theSpinner.setVisibility(View.VISIBLE); | |
theItems.setVisibility(View.GONE); | |
} else { | |
theSpinner.setVisibility(View.GONE); | |
theItems.setVisibility(View.VISIBLE); | |
} | |
} | |
static State loadData() throws InterruptedException { | |
Thread.sleep(10_000); | |
List<String> items = Arrays.asList( | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.", | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.", | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.", | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet."); | |
return of -> of.loaded(items); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MainActivity : AppCompatActivity() { | |
internal val adapter = LipsumAdapter() | |
internal lateinit var my: Scope | |
internal lateinit var theItems: RecyclerView | |
internal var pending: Future<*>? = null | |
override fun onCreate(savedInstanceState: Bundle?) { | |
my = lastCustomNonConfigurationInstance as? Scope ?: Scope() | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_coordinator_test) | |
theItems = (findViewById(R.id.the_items) as RecyclerView).apply { | |
adapter = [email protected] | |
layoutManager = LinearLayoutManager(context) | |
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL)) | |
} | |
} | |
override fun onRetainCustomNonConfigurationInstance(): Any = my | |
override fun onResume() { | |
super.onResume() | |
update(my.state) | |
} | |
override fun onPause() { | |
super.onPause() | |
pending?.cancel(true) | |
} | |
internal fun update(next: State): Unit = runOnUiThread { | |
my.state = next | |
when (next) { | |
is Unknown -> update(Loading(my.io.submit(::loadData))) | |
is Loading -> { | |
pending = my.io.submit { | |
try { | |
update(next.task.get()) | |
} catch (e: InterruptedException) { | |
} catch (e: ExecutionException) { | |
update(Error(e)) | |
} finally { | |
pending = null | |
} | |
} | |
} | |
is Loaded -> adapter.items = next.items | |
is Error -> error(next.e) | |
} | |
} | |
} | |
internal class Scope { | |
val io: ExecutorService = Executors.newCachedThreadPool() | |
var state: State = Unknown | |
} | |
sealed class State | |
object Unknown : State() | |
data class Loading(val task: Future<State>) : State() | |
data class Loaded(val items: List<String>) : State() | |
data class Error(val e: Throwable) : State() | |
internal fun loadData(): State { | |
Thread.sleep(10_000) | |
return Loaded(listOf( | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.", | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.", | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.", | |
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur malesuada id tortor sit amet scelerisque.", | |
"Integer facilisis sem et sapien tempor, vel semper risus ultrices. Aenean molestie turpis ipsum, id ultricies tortor dictum a.", | |
"Pellentesque et eleifend libero. Phasellus vestibulum consectetur arcu, id tincidunt magna luctus sit amet.")) | |
} | |
internal class LipsumAdapter : RecyclerView.Adapter<LipsumAdapter.RowView>() { | |
internal class RowView(itemView: View) : RecyclerView.ViewHolder(itemView) { | |
val root: TextView = itemView as TextView | |
init { | |
itemView.isClickable = true | |
} | |
fun show(item: String) { | |
root.text = item | |
} | |
} | |
internal var items: List<String> = Collections.emptyList() | |
set(value) = notifyDataSetChanged() | |
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = LayoutInflater | |
.from(parent.context) | |
.inflate(android.R.layout.simple_selectable_list_item, parent, false) | |
.let(::RowView) | |
override fun onBindViewHolder(holder: RowView, position: Int) = holder.show(items[position]) | |
override fun getItemCount(): Int = items.size | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment