Outdated documentation #1

Closed
giannello opened this Issue Mar 30, 2012 · 15 comments

3 participants

@giannello

I'm trying to integrate propoid in a new application but it seems that the documentation is not up-to-date, some examples doesn't work.

public class Foo extends Propoid {

    public final Property<String> name = property();

    public Foo() {
    }
}

in the activity's onCreate

        Repository foos = new Repository(this, "foos");

        Foo foo = new Foo();
        foos.insert(foo);

        setListAdapter(new GenericAdapter(foos.query(new Foo())));

The error is "Cannot instantiate the type GenericAdapter", and a little investigation led to the fact that the GenericAdapter is an abstract class. How is it supposed to be implemented?

@svenmeier
Owner

Sorry, GenericAdapter doesn't offer a magic binding of properties to views. You still have to implement a bind() method:

protected void bind(int position, View view, Foo foo) {
}

I've corrected the example on https://github.com/svenmeier/propoid

@svenmeier svenmeier closed this Mar 30, 2012
@giannello

Thanks!
Are there any plans to implement an automagic binding via reflections or annotations?

@giannello

I've just tried the new code, but still no luck.

        setListAdapter(new GenericAdapter<Foo>(repository.query(Foo.class)) {
            protected void bind(int position, View view, Foo foo) {
            }
        });

leads to this error

The constructor GenericAdapter<Foo>(Match<Class<Foo>>) is undefined
@svenmeier
Owner

Thanks for pressing me to improve the documentation: query() returns a Match object, the adapter needs a list. Now corrected in the sample.

@svenmeier
Owner

Are there any plans to implement an automagic binding via reflections or annotations?

No plans currently. The meta information about properties is all available already, but I'm not yet decided where place the required binding information. Some libraries put meta information into the layout xml (which view to bind to which property) but I prefer having most non-layout related stuff in Java code.

@giannello

It worked, thanks!
Just a few things:
I'm using

repository.query(new Foo())

instead of

repository.query(Foo.class())

the error is

Bound mismatch:
The generic method query(P) of type Repository is not applicable for the arguments (Class<Foo>).
The inferred type Class<Foo> is not a valid substitute for the bounded parameter <P extends Propoid>

and there is a typo in your documentation ("listView.setAdapater" instead of "listView.setAdapter").

@svenmeier
Owner

query(new Foo())

Of course, that's correct. Thanks for your interest in propoid.

@giannello

Activity:

setListAdapter(new FooAdapter(R.layout.foo_list, repository.query(new Foo()).list()));

class FooAdapter

package org.example.test;
import java.util.List;

import propoid.ui.Index;
import propoid.ui.bind.TextBinding;
import propoid.ui.list.GenericAdapter;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class FooAdapter extends GenericAdapter<Foo> {

    private static final String TAG = "FooAdapter";

    protected FooAdapter(List<Foo> items) {
        super(items);
    }

    protected FooAdapter(int layoutId, List<Foo> items) {
        super(layoutId, items);
    }

    @Override
    protected void bind(int position, View view, Foo foo) {
                Index index = Index.get(view);
                TextBinding.string(foo.name, index.<TextView>get(R.id.foo_list_name));
    }

}

foo_list.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp"
    android:id="@+id/foo_list_name" >
</TextView>

After launching the app, it throws this exception:

 FATAL EXCEPTION: main
 java.lang.ClassCastException: propoid.ui.Index cannot be cast to propoid.ui.bind.Binding
    at propoid.ui.bind.Binding.<init>(Binding.java:52)
    at propoid.ui.bind.TextBinding.<init>(TextBinding.java:53)
    at propoid.ui.bind.TextBinding.string(TextBinding.java:149)
    at org.example.test.FooAdapter.bind(FooAdapter.java:28)
    at org.example.test.FooAdapter.bind(FooAdapter.java:1)
    at propoid.ui.list.GenericAdapter.getViewImpl(GenericAdapter.java:180)
    at propoid.ui.list.GenericAdapter.getView(GenericAdapter.java:163)
    at android.widget.AbsListView.obtainView(AbsListView.java:2033)
    at android.widget.ListView.makeAndAddView(ListView.java:1772)
    at android.widget.ListView.fillDown(ListView.java:672)
    at android.widget.ListView.fillFromTop(ListView.java:732)
    at android.widget.ListView.layoutChildren(ListView.java:1625)
    at android.widget.AbsListView.onLayout(AbsListView.java:1863)
    at android.view.View.layout(View.java:11283)
    at android.view.ViewGroup.layout(ViewGroup.java:4224)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
    at android.view.View.layout(View.java:11283)
    at android.view.ViewGroup.layout(ViewGroup.java:4224)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
    at android.view.View.layout(View.java:11283)
    at android.view.ViewGroup.layout(ViewGroup.java:4224)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
    at android.view.View.layout(View.java:11283)
    at android.view.ViewGroup.layout(ViewGroup.java:4224)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
    at android.view.View.layout(View.java:11283)
    at android.view.ViewGroup.layout(ViewGroup.java:4224)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1489)
    at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4424)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    at dalvik.system.NativeStart.main(Native Method)
@svenmeier
Owner

Both Index and Binding instances use the view's setTag() to store themself with the view. I've improved the failure message.

If your item layout consists of a single TextView only, you should just cast the passed view (no index needed):

@Override
protected void bind(int position, View view, Foo foo) {
    TextBinding.string(foo.name, (TextView)view);
}
@giannello

It's working now, thank you.
The single TextView was just a fake layout for testing. Using a LinearLayout with nested TextViews works like a charm with Index. I'll try binding models to form elements tomorrow.
Please, find a nice logo for your project, I'd like to backlink it from my project's page.

@giannello

Hello again, Sven.
Binding models to form elements works, using this code:

        foo = new Foo();

        TextBinding.string(foo.bar, findViewById(R.id.foo_add_bar));
        TextBinding.string(foo.baz, findViewById(R.id.foo_add_baz));

I have an options menu with a "Save" button which does a simple

repository.insert(foo)

and it gets saved.
Now, in the ListView, I can see the new element. On the same ListView, I have a ContextMenu which allows me to delete the objects.

@Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.foos_context_menu, menu);
    }

@Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) {
            case R.id.aircrafts_context_delete:
                ListView lv = getListView();
                repository.delete((Foo) lv.getItemAtPosition(info.position));
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }

The ListView containing all the Foos still shows the deleted Foo.
Should I manually reload the ListView or delete the corresponding row?

@svenmeier
Owner

The list view adapter is holding a database cursor which still has the deleted object.

You have to set a new adapter on your listView. If you extends GenericAdapter, the previous cursor is automagically closed.

If you use the convenience #install() method of GenericAdapter, the list will keep its scroll position:

new FooAdapter().install(listView);
@tmarkle

I am having trouble using this library because I don't know how to properly add it to my project. Can I get quick documentation for getting started?

@tmarkle

Nevermind, I got it implemented by import->filesystem then renaming the packages to the values specified in the files.
I can't use the library though because I am populating my objects using Gson and it can't parse into the Property type.

@giannello

Yep, importing the library is quite a pain, since you can't do a simple "git submodule add".
I ended up making a git clone of the full repo then manually copying the packages under /src/propoid in my android project folder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment