Giter VIP home page Giter VIP logo

declex's Introduction

DecleX

Android Arsenal Join the chat at https://gitter.im/declex/Lobby

DecleX

DecleX is a powerful framework which reduces the verbosity of Java language, and enhances the dependencies/views injections to permitting the creation of Android applications at record speeds. It is totally based on AndroidAnnotations; in a similar fashion, we want to facilitate the writing and the maintenance of Android applications to the highest level which has not been achieved up to now.

Documentation

Please consult our Wiki in https://github.com/smaugho/declex/wiki

Configuration

Place the following lines in your app module build.gradle file:

dependencies {
    annotationProcessor 'com.dspot:declex:2.0.a.24'
    implementation 'com.dspot:declex-api:2.0.a.24'
    implementation 'com.dspot:declex-actions:2.0.a.21'
}

And that's it!...

If you need to use the configuration for the old version of Android Application Plugin with 'android-apt' you can check it here: Old Android Application Plugin Configuration

Examples

See our example projects in Examples

Articles


Sponsored by DSpot Sp. z o.o. Contact us at [email protected]

declex's People

Contributors

drobinetm avatar gitter-badger avatar smaugho avatar z3phyro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

declex's Issues

OnFail for Model Actions

The model actions ($PutModel, $GetModel, $Recollect, $Populate) should have their corresponding Failed selector, so that the programmer should add behaviors for instance, if the $Recollect failed because of the validation.

Maybe the "Failed" for $PutModel and $GetModel should be separated from the Failed for the $Recollect and $Populate, since these two actions are embedded in the $Put and $Get Model actions.

Add actions support for intent

Add a support for Intents in the actions, including some default behavior for specific intents.

It would be nice to have Intents for the camera and gallery images that would write automatically the code, included the methods to be called onActivityResult.

For instance, all this is involve in a request to select a picture from the gallery:

            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");
            startActivityForResult(intent, Config.GALLERY_REQUEST_NEW);
    @TargetApi(Build.VERSION_CODES.KITKAT)
    @OnActivityResult(Config.GALLERY_REQUEST_NEW)
    void onGalleryNewIntentResult(int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
            final int takeFlags = data.getFlags() & (
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
            );

            Uri uri = data.getData();

            // Check for the freshest data
            getActivity().getContentResolver().takePersistableUriPermission(uri, takeFlags);

            Picasso.with(getContext()).load(uri).resize(140, 140).centerCrop().into(target);
        }
    }
Target target = new Target() {
        @Override
        public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
            String destFolder = getActivity().getCacheDir().getAbsolutePath();

            try {
                FileOutputStream out = new FileOutputStream(destFolder + "/image.png");

                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

                RestAdapter restAdapter = new RestAdapter.Builder()
                        .setEndpoint(Config.SERVER)
                        .build();

                TypedFile image = new TypedFile("application/octet-stream", new File(destFolder + "/image.png"));
                restAdapter.create(ImageStore.class).storeImage("Bearer " + user.getApiToken(), profile.getRole(), profile.getRemoteId(), image, new Callback<Profile_>() {

                    @Override
                    public void success(Profile_ result, Response response) {
                        profile.setPhoto(result.getPhoto());
                        profile.setFullPhotoURL(result.getFullPhotoURL());
                        profile.save();
                        UpdateUIEvent_.post();
                    }

                    @Override
                    public void failure(RetrofitError error) {

                    }
                });

            } catch (FileNotFoundException e) {

            }
        }

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {

        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }
    };

About the target, it would be good to implement a simple upload method for images and files in DecleX too ;)

Try-Catch support for Actions

Action should support to be written within Try-Catch blocks. There's many situation in with it is completely necessary to use methods that should which errors should be catch. One problem with this, it is that the action mechanism creates several runnables to execute the overall action, and this will force to place the try catch in all of them equally.

@OverrideAction to directly override methods

In a scenario in which an action is applied to an override method, and it is needed to call the super method from within this method, it is not possible to do so right now, for instance, let's say that in an activity the method onBackPressed should be override, and the super.onBackPressed should be called, for instance:

    @Override
    @Action
    public void onBackPressed() {
        $SaveProfile();
        if (something) {
            super.onBackPressed();
        }
    }

In such scenario, the generated action method cannot call super.onBackPressed for the parent of this activity (ex. Activity), because it cannot bypass the onBackPressed method of the current activity. A proposed mechanism is to create the annotation @OverrideAction, (which will forced the mothod to be named ending with "_"), in this case the generated action method can call the super.onBackPressed without problems:

    @OverrideAction
    public void onBackPressed_() {
        $SaveProfile();
        if (something) {
            super.onBackPressed();
        }
    }

It would be good to detect from within the action if this happens, to indicate to the programmer to use the @OverrideAction annotation, instead of @action or any other @action activated annotation.

"withResult" for Activity Actions

Activities can now only be opened using DecleX, of course, DecleX gives access to the internal Builder, so that a more complex operation can be done.

But if you want to call an activity, and then execute some code with the result of it, the code is something like this:

    private final int PROFILE_RESULT = 0x1212;

    @Click
    void userProfile() {
        $ProfileActivity().builder().startForResult(PROFILE_RESULT);
    }

    @OnActivityResult(PROFILE_RESULT)
    void onProfileActivityReturned() {
        $GetModel(profile);
        if (!profile.exists()) userLogout();
    }

But this is using AndroidAnnotations capabilities to simplify the code.. but all this code can be simpler using DecleX, it should be enough with:

    @Click
    void userProfile() {
        $ProfileActivity().withResult();

        $GetModel(profile);
        if (!profile.exists()) userLogout();
    }

Right now, the Actions are limited to the method that implement them, in the case above, the Action should make the Runnable that runs the code after the result is received public, so that it is accessible from the Activity (or Fragment) in anyplace, then that runnable will be called when the result is received.

It is importart to note that making this mechanism with open the possibility to make the same for more complex Actions (this mechanism can be directly applied to the Intents for instance as stated in the Issue #5)

List populator problem in @ItemClick when using String class

When using a list populator with its @ItemClick method like this:

@Populator
List<String> list = Arrays.asList("Text1", "Text2", "Text3");

@ItemClick
void list(String item) {
    //Do something
}

The framework doesn't handle the list method correctly and pass the String parameter as String_, treating the populator method as a @model.

Make @ServerModel Put and Get Operations Thread Save

@ServerModel operations should not be called in the MainThread, because a NetworkOnMainThread error will be through by the system. So, the programmer should be aware of this, and always in a @model, specify the "async=true" param.

It would be good to prepare a mechanism to run this kind of operations in background always, to make the programming easier, and also this simplify more the code, and makes that starter programmers don't have to worried for the concept of Threads..

Remove requirement of Build for DecleX Actions Holders

To extend the creation of Actions not only for event-based actions, but also for normal actions (similar to beans), remove the need to have a build method, in that case, DecleX should automatically call all the things that would be in this build method, when the action ends.

Troubles with @AdapterClass and @ItemClick

When is used an @AdapterClass and is set a @ItemClick, this @ItemClick can't set an event onClickListener to the list items:

@Model
@Populator
@AdapterClass(ObjectAdapter.class)
List<Object_> objectList;

@ItemClick
void objectList(Object_ model) {
    
}

public abstract class ObjectAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
	
}

By other way, the @click can set the event onClickListener using a reference to the item view id:

@Click(R.id.itemObject)
void clickOnItem(Object_ model) {

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/objectList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:dividerHeight="0dp"
        android:divider="@null"
        tools:listitem="@layout/itemObjectLayout" />

</LinearLayout>

This is the itemObjectLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/itemObject"
    >
    
</RelativeLayout>

View can't be obtained when ItemClicked.

When I declared a item_layout with some view like RelativeLayout (id=relDate), and it is called in the @ItemClick annotations from it params:

@ItemClick
void horizontalList(final View relDate,DateWeek_ model) {
//Do somethings with relDate and model
}

The idea is to modify relDate and it childrens views with info of model, so relDate is not recognized, it is not obtained correctly.

Implement ModelList for Models Lists

The method getModelList_ can implement (and return) a custom List named ModelList. This is an abstract class that includes a method named save.

A @LocalDBModel will implement a custom ModelList, that will save every element in a Transaction, so it would be enough to call models.save(), where models is the list of injected Models, to save every element in a transaction.

With this can be implemented also a List Upload for the server model.

Lists don't cast correctly in adapter for models that are not @LocalDBModels

If a list populator is used with a model that is not annotated with @LocalDBModel:

@UseModel
public class MyModel {

}


@Model
@Populator
List<MyModel> myList;

This is not handled properly and MyModel is not casted in the generated Adapter to MyModel_, so it should be done only like:

@Model
@Populator
List<MyModel_> myList;

This is a bug that should be fixed.

Remark: it works properly for models annotated with @LocalDBModel.

Formatted Syntax in initializators

In the actions, it would be great if the Formatted Syntax is accepted for string initializators, for instnces:

@Action
void someAction() {
    $DateDialog();
    int $year = 0, $month = 0, $day = 0;
    
    String formattedString = "The year is {$year} and the month is ${month}";
}

@PreferenceModel to store a model in preferences, and read from.

Right now DecleX includes two type of @models,

@LocalDBModel for SQLite management
@ServerModel to connect to the server

It would be good to make a @PreferenceModel that store and read a model to/from the Preferences. Since the models mechanism is much more straight forward than AndroidAnnotations mechanism.

Conflict in generated class with two view with the same "id"

When you set a listView with some kind of item that contains views with "id" that have been declared in the view of listView, so when you write a method and need to pass in parameters this components with the same "id" that you need to work, in the generated class declex make a conflict with that components. Here a example code of this:

First Layout is main, wich contain a that have the listView and other that have a view with some components that have the same id of the component in the other Layout (item_professor_lesson_list_edit)....

Layout: main.xml

<LinearLayout
        android:id="@+id/form_add_lesson"
        android:layout_below="@id/rel_add"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginTop="8dp"
        android:visibility="gone"
        android:paddingRight="19dp"
        android:paddingLeft="19dp"
        android:paddingBottom="@dimen/origin_14dp">

       <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

            <co.tutorbox.util.SansproTextView.SansproTextViewSemibold
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="Class name"
                android:layout_centerVertical="true"
                android:textSize="19dp"
                android:layout_marginRight="20dp"
                android:id="@+id/class_name" />

            <include
                layout="@layout/item_search"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/class_name"
                android:layout_toEndOf="@+id/class_name"
                android:layout_marginLeft="16dp" />

        </RelativeLayout>

        <!-- Class Length:::::::::::::::::::::::::::::::::::::::::::::-->
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            >

            <co.tutorbox.util.SansproTextView.SansproTextViewSemibold
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="Class length"
                android:id="@+id/class_length"
                android:layout_centerVertical="true"
                android:textSize="19dp" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="right"
                android:layout_alignParentRight="true">


                <Button
                    android:layout_width="54dp"
                    android:layout_height="32dp"
                    android:background="@drawable/common_btn"
                    android:text="30m"
                    android:gravity="center"
                    android:layout_gravity="center_horizontal"
                    android:textSize="@dimen/origin_16sp_text_size"
                    android:textColor="#404040"
                    android:id="@+id/btnTimeShort" />

                <Button
                    android:layout_width="54dp"
                    android:layout_height="32dp"
                    android:background="@drawable/common_btn"
                    android:text="45m"
                    android:gravity="center"
                    android:layout_gravity="center_horizontal"
                    android:textSize="@dimen/origin_16sp_text_size"
                    android:textColor="@color/white"
                    android:layout_marginLeft="@dimen/origin_14dp"
                    android:id="@+id/btnTimeMedium" />

                <Button
                    android:layout_width="54dp"
                    android:layout_height="32dp"
                    android:background="@drawable/common_btn"
                    android:text="60m"
                    android:gravity="center"
                    android:layout_gravity="center_horizontal"
                    android:textSize="@dimen/origin_16sp_text_size"
                    android:textColor="@color/white"
                    android:layout_marginLeft="@dimen/origin_14dp"
                    android:id="@+id/btnTimeLong" />
            </LinearLayout>

<LinearLayout
        android:layout_below="@id/form_add_lesson"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

<ListView
            tools:listitem="@layout/item_professor_lesson_list_edit"
            android:background="@color/white">

Next Layout.....

Layout: item_professor_lesson_list_edit.xml
<RelativeLayout
        android:layout_width="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="19dp"
        android:layout_marginRight="19dp"
        android:layout_height="wrap_content">

        <co.tutorbox.util.SansproTextView.SansproTextViewSemiboldGreen
            android:id="@+id/lesson_formattedCategoryAndName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:textSize="19dp"
            android:maxWidth="@dimen/origin_160dp"
            android:lines="1"

            android:paddingBottom="10dp"
            android:textColor="#00b992"
            android:ellipsize="end"
            android:text="Music - Guitar" />

        <TextView
            android:id="@+id/lesson_formattedLengthAndPrice"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:textSize="@dimen/origin_14sp_text_size"
            android:layout_marginLeft="@dimen/origin_2dp"
            android:layout_toRightOf="@+id/lesson_formattedCategoryAndName"
            android:textColor="#999"
            android:textStyle="bold"
            android:paddingBottom="10dp"
            android:text="(30 min, $56)"
            android:layout_centerVertical="true" />

    </RelativeLayout>

    <LinearLayout
        android:id="@+id/form_edit_lesson"
        android:layout_below="@id/rel_add"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:background="#f0f0f0"
        android:layout_marginTop="65dp"
        android:visibility="visible"
        android:paddingBottom="@dimen/origin_14dp">

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_marginLeft="19dp"
            android:layout_marginRight="19dp"
            android:layout_height="wrap_content">

            <co.tutorbox.util.SansproTextView.SansproTextViewSemibold
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="Class name"
                android:layout_centerVertical="true"
                android:textSize="19dp"
                android:layout_marginRight="20dp"
                android:id="@+id/class_name" />

            <include
                layout="@layout/item_search"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/class_name"
                android:layout_toEndOf="@+id/class_name"
                android:layout_marginLeft="16dp" />

        </RelativeLayout>

        <!-- Class Length:::::::::::::::::::::::::::::::::::::::::::::-->
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_marginLeft="19dp"
            android:layout_marginRight="19dp"
            android:layout_height="wrap_content"
            >

            <co.tutorbox.util.SansproTextView.SansproTextViewSemibold
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="Class length"
                android:id="@+id/class_length"
                android:layout_centerVertical="true"
                android:textSize="19dp" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="right"
                android:layout_alignParentRight="true">


                <Button
                    android:layout_width="54dp"
                    android:layout_height="32dp"
                    android:background="@drawable/common_btn"
                    android:text="30m"
                    android:gravity="center"
                    android:layout_gravity="center_horizontal"
                    android:textSize="@dimen/origin_16sp_text_size"
                    android:textColor="#404040"
                    android:id="@+id/btnTimeShort" />

                <Button
                    android:layout_width="54dp"
                    android:layout_height="32dp"
                    android:background="@drawable/common_btn"
                    android:text="45m"
                    android:gravity="center"
                    android:layout_gravity="center_horizontal"
                    android:textSize="@dimen/origin_16sp_text_size"
                    android:textColor="@color/white"
                    android:layout_marginLeft="@dimen/origin_14dp"
                    android:id="@+id/btnTimeMedium" />

                <Button
                    android:layout_width="54dp"
                    android:layout_height="32dp"
                    android:background="@drawable/common_btn"
                    android:text="60m"
                    android:gravity="center"
                    android:layout_gravity="center_horizontal"
                    android:textSize="@dimen/origin_16sp_text_size"
                    android:textColor="@color/white"
                    android:layout_marginLeft="@dimen/origin_14dp"
                    android:id="@+id/btnTimeLong" />
            </LinearLayout>

        </RelativeLayout>

        <!-- Price per Lesson:::::::::::::::::::::::::::::::::::::::::::::-->
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="19dp"
            android:layout_marginRight="19dp"
            android:layout_marginTop="15dp"
            >

            <co.tutorbox.util.SansproTextView.SansproTextViewSemibold
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Price per Lesson"
                android:id="@+id/class_price"
                android:layout_centerVertical="true"
                android:textSize="19dp" />

            <EditText
                android:layout_width="@dimen/origin_100dp"
                android:layout_height="40dp"
                android:layout_centerVertical="true"
                android:layout_alignParentRight="true"
                android:background="@drawable/common_btn_pressed"
                android:hint="Price"
                android:textColor="#404040"
                android:textSize="@dimen/origin_16sp_text_size"
                android:layout_gravity="center_vertical"
                android:textAlignment="gravity"
                android:textColorHint="#545454"
                android:id="@+id/lesson_price"
                android:inputType="numberDecimal" />

        </RelativeLayout>

        <Button
            android:layout_width="fill_parent"
            android:layout_height="60dp"
            android:background="@drawable/button_reschedule"
            android:text="Edit lesson"
            android:layout_marginTop="25dp"
            android:padding="@dimen/origin_14dp"
            android:textAlignment="gravity"
            android:layout_marginRight="19dp"
            android:layout_marginLeft="19dp"
            android:gravity="center_horizontal"
            android:layout_gravity="center_horizontal"
            android:textSize="@dimen/origin_18sp_text_size"
            android:textStyle="bold"
            android:textColor="#fff"
            android:visibility="visible"
            android:id="@+id/btnAddLesson" />


    </LinearLayout>

Now in the java code, when we make this:

public void form_edit_lesson(LinearLayout linearLayout, AutoCompleteTextView search_box, EditText lesson_price){
      search_box.setText("I'm an AutoCompleteTextView");
      lesson_price.setText("I'm an EditText");
        if(someCondititions){
        linearLayout.setVisibility(View.VISIBLE);
        }
        else{
            linearLayout.setVisibility(View.GONE);
        }
    }

Declex make conflicts in the generated class with the AutoCompleteTextView and with the EditText.

ActiveAndroid automatic model change detection

Prepare a mechanism to detect the changes in @ActiveAndroid models, to create the migrations automatically, avoiding having to create the migration files.

For instance, if you have already a class User, and you add a new field (let's say "image") to it, and the db is already created, create the migration mechanism automatically.

There's many things that should be taken in consideration, including the fact that some times it is not necessary to create some migrations, since the app is not in production yet.

Maybe it would be good to "inform" to DecleX about the app being in production already, so that it starts creating the migrations automatically.

Actions should permit be referenced in any Java-valid way

Right now the Actions can be referenced inside an Actions Method, only with the name starting by $, for instance: $DoSomething(), but the framework should be able to support also:

Action.$DoSomething()

or

com.dspot.declex.Actoin.$DoSomething()

String @Populator assumes a "text" field

In populators of type String, if text id was not specify, assume the whole view (rootView) is the one that is gonna be assigned. This can solve the use of System layouts for the components.

Activity Action "builder" to "intent" and detect access to "get" method.

It is necessary to rename "builder" parameter in Activity Action to builder. And it is necessary to stop the Action from being executed (included the call to build as well), if a specific method is detected, after accessing another... for instance

    Intent intent = $MainActivity().intent().extra("type", type).get();

In this example, if after calling "intent" a call to the method "get" is detected, then the call was used to create the intent (and not to run the activity).

References to "this" not working in Actions

In the actions, the references to "this" doesn't work , the problem is that the action generate runnables, and inside these runnables, "this" references the Runnable itself, and not the upper class.

FragmentPageAdapter for ViewPager

Implements support for the FragmentPageAdapter as a Populate for ViewPager... a common code is:

    @ViewById
    ViewPager viewPager;

    @AfterViews
    void setMyRosterViewPager(){
        PagerAdapter pagerAdapter = new MyRosterFragmentPagerAdapter(getFragmentManager());

        viewPager.setAdapter(pagerAdapter);
    }

and all the FragmentPageAdapter (MyRosterFragmentPageAdapter) should be implemented, I'm thinking in something like:

@Populator
List<Fragment> viewPager = Arrays.asList(Fragment1.class, Fragment2.class, Fragment3.class);

The action $Populate should work with it too, so that the List can be changed at runtime if it is necessary.

The adapter should be generated automatically... it should also give support for the annotation @AdapterClass, so that the generated adapter could be configured.

"model" param in @ServerRequest, should accept method names too

@ServerRequest model param accepts "this" special keywords, and fields, but it would be great if it can accept methods with 1 param too, in this way more complex operations could be done over the data that is return from within the server

Ex.

@ServerModel(
        baseUrl = Config.SERVER,

        put = {
                @ServerRequest(
                        name = "create",
                        action = "records/update/booking",
                        model = "update"
                )
        }
)

@LocalDBModel
@UseModel
@EBean
public class Booking extends Model {

    @Column
    String schedule;
    @Column
    boolean confirmed;

    public void update(Booking from) {
        Booking booking = (Booking) from;

        this.schedule = booking.schedule;
        this.confirmed = booking.confirmed;
    }

}

After $PutModel and $GetModel return to the Main Thread

Right now, after a $PutModel or $GetModel is executed, if it was executed in the background, then if you want to make any change in the UI, need to implicitly write the action $UIThread, for instance:

$PutModel(myModel);
$UIThread();
//Do something here in the UI.

But $PutModel knows at priori if the action is executed in the background or not, so, it would be nice to invoke the next runnable in the list of actions already in the UIThread avoiding the errors that would occurs if the programmer doesn't write the $UIThread annotation.

@AdapterClass for RecyclerView

@AdapterClass supports only the creation of Adapters for AdapterView descendant, it should work with RecyclerView as well

@Action declarations for methods (quick Actions) inside Action Methods

It would be useful to have a @action variable declaration that forces a method inside an action (annotated with this field) to be sequenced and included in the Actions mechanism.

Let's say we have the following code:

    @Click
    void toolbar_back() {
        saveAvailability();
        getActivity().onBackPressed();
    }

    @Action
    void saveAvailability() {
        Dialog progress = $ProgressDialog().message("Saving...").dialog();

        $PutModel(hours).orderBy(prepareAvailability());
        if ($PutModel.Failed) {
            $Toast("An error occurred: {e}: {e.getMessage()}");
            progress.dismiss();
        }

        progress.dismiss();
    }

If we want that the first action second method getActivity().onBackPressed() be executed after the saveAvailability method return, the only way to do it is to pass a Runnable Parameter, forcing the programmer to build a new action (lot of boilerplate for only one case), or to pass a Runnable as parameter... if we add support for the methods to behave similar to the "build" method of an action, this would add much more power to DecleX Actions. For instance:

    @Click
    void toolbar_back() {
        saveAvailability();
        getActivity().onBackPressed();
    }

    @Action
    void saveAvailability() {
        @Action Runnable next = null;

        Dialog progress = $ProgressDialog().message("Saving...").dialog();

        $PutModel(hours).orderBy(prepareAvailability());
        if ($PutModel.Failed) {
            $Toast("An error occurred: {e}: {e.getMessage()}");
            progress.dismiss();
        }

        progress.dismiss();
        next.run();
    }

These fields can follow the same rules than the parameters of the "build" methods in Action Holders.

Re-defined @UseEventBus.

When you use annotations for event(@UseEventBus) in a class that is inherited by another that use @UseEventBus too, in the generated class an error ocurrs by duplicated method generated for this.
For example:
This is the class that is inherited by others:

@UseEventBus
@EFragment(R.layout.bar_navigation)
public class TeacherStudentBaseFragment extends CommonFragment {
    @Model
    protected User_ currentUser;
}

Now, this class inherits SearchFragment and need to have @UseEventBus too, with the event onUpdateBadge:


@UseEventBus
@EFragment(R.layout.fragment_search)
public class SearchFragment extends TeacherStudentBaseFragment {

@ViewById
    TextView new_request;

@Event
    void onUpdateBadge(int setCount){
        new_request.setText(""+setCount);
    }
}

When is compilated, we have in the in SearchFragment class a conflict, because the generated methods for the @UseEventBus are repeated.

Create $Notification action

Create $Notification action to handle the System Notifications with its builder, it would have features like automatic showing (and canceling) auto generating a Notification ID for it, auto integration with Pending Intents, automatic download of URLs with Picasso.

Override Actions

It is needed an exception for the next kind of actions:

@action
@OverRide
public void onResume() {
super.onResume();
$InvokeAction();
}

In java you cannot call the super.super method, so it cannot be implemented in the generated class the call to the super.onResume (that will call this method).

From here there's two things that can be implemented, first, to execute actions on special methods (so, no overriding actions), the "_" symbol can be add o the end:

Ex.
@action
void onResume_() {
$InvokeActionsHere();
}

But if what is required is to override the onResume, it can be done indicating this in some flag in the @action annotation:

@action(override=true)
void onResume_() {
super.onResume();
$InvokeActionsHere();
}

this will guarantee the generated action will override onResume, and the code executed will be that of the Action Method.

Controller for Model operations

A Controller is required for Model operations (Ex. Load, Put model). This can be used by Model implementations to insert operations (like "cancel").

For instance, right now the $PutModel action over a @ServerModel doesn't have a way to stop the Network operation.

This can be implemented adding to $PutModel and $GetModel a Controller field, that will return this ModelController object.. With it, the operation can be canceled:

    ModelController controller = $PutModel(user).controller();

    ...
    controller.interrupt();

This method is generic.

It can be done, passing as parameter this controller object to the getModel_ operations... inside, each operation can add-remove operation listeners, for instance, for the server model.

    final Call call = request.newCall();

    OperationListener listener = new OperationListener() {
        @Override
        public void onInterrupt() {
            call.cancel();
        }
    };
    controller.addOperationListener(listener)

    call.execute();
   
    ....
    controller.removeOperationListener(listener);

This can be done for every blocking operation (that can be canceled)... so independent of how the Model is implemented, using this mechanism it can be controlled the operations.

Specify in the @Model annotation, the fields to put (as a string)

When the action $PutModel is executed, in the case of a @ServerModel the instance is serialized completely and sent to the server. This is controlled by a parameter named "fields" in the @ServerModel annotation. But this cannot be controlled from within the @model injection itself, and this could be very important and efficient sometimes.

So, the @model should have a "fields" param to take the fields to submit.

Also, this can be useful as well with @LocalDBModel, so in general, the "fields" field can be used in all the models.

the methods $PutModel shoud have a method "fields" as well to override this behavior easily programmatically.

Inflating Layouts with Populators and @ViewById

It's no possible to inflate a header view into a layout, and call an element that belongs to header view using @ViewById, like as:

@ViewById(R.id.example)
    PieChart example;

@Populator(R.layout.my_header)
    List<String> my_data_list = Arrays.asList("News1", "News2", "News3", "News3", "News3");

 @AfterViews
    void setViews(ListView my_data_list , View my_header$view){
        my_data_list.addHeaderView(my_header$view);
        example.setUsePercentValues(true);
    }

Instead set a parameter into the function with @AfterViews, like as:

@Populator(R.layout.my_header)
    List<String> my_data_list = Arrays.asList("News1", "News2", "News3", "News3", "News3");

 @AfterViews
    void setViews(ListView my_data_list , View my_header$view, PieChart example){
        my_data_list.addHeaderView(my_header$view);
        example.setUsePercentValues(true);
    }

JavaDoc for Actions

Actions should have JavaDoc, to go to the classes or methods that generated the action.

For the built-in Actions it would be good also to insert JavaDoc to have a quick explanation of how the actions works.

PutModel with fields

It would be good to have a fields parameter that can be used on $PutModel, ServerModels right now put all the fields always to the server, and this can be sometimes not the best efficient or preferred way to upload data to the server.

@model(fields="name, last_name")

And in the query:

$PutModel(model).fields("name, last_name");

Annotations Dependency Injection

To make the Annotating process even simpler, it would be nice to make Annotations Dependency Injection (ADI). This feature will permit to resolve and run the dependencies of an annotation. Let's say we want to use @event annotation, but this annotations requires to annotate the Enhanced component with @UseEventBus, so the annotation instead of failing if it is not annotated the class properly with EventBus, in the case of not @UseEventBus annotation present, the validate method will call the validate method of the UseEventBusHandler, and the process method will call the process method of that handler. After is called the method in the handler for no-annotation present dependency, then the other handlers "will know" the method was already called, avoiding multiple calls.

Another way to accomplish this is that the method that process the handlers read from other handlers a Dependency list, solving the dependencies, and ensuring to process those dependencies.

See that this can be done with annotations that run without parameters clearly, so the ADI should take this into account.

Assigning action to assign value to a field doesn't work properly

If an action method result is assigned to a field, in the generated code for the action, this is never assign to the field, instead a new variable is created:

    Dialog progressDialog;

    @Click
    void btnLoginFb() {
        $FacebookLogin();

        //Here the dialog is never assigned to the field, at least that he field name starts with '$'
        progressDialog = $ProgressDialog().message("Sign up in progress...").dialog();
    }

UseGson for models

@ServerModel implements all a mechanism that can be used in a more generic way (as a new @UseGson).. Right now implementing this will require to make much more declarations of annotations in Models, but if #44 (ADI) is implemented this can be easily handle, making the annotation available for other uses.

Anonymouse classes should be permitted in actions

Anonymous classes are right now permitted in actions, but this is an important limitation, there should be permitted. Since it is a problem to process the actions inside, at least the framework should permit to use them without Actions on its methods.

NavigationDrawer Error for latest support libraries

For the version 23 of the support library, the Navigation Items cannot be accessed since the findViewById in the activity doesn't get the item (it should be executed in the Navitation Item object itself)

Model params in @PutOnEvent, @LoadOnEvent, @UpdateOnEvent, PutOnAction,

The event driven Put, Load and Updates simplifies greatly the code but the model cannot be provided with a specific Query, OrderBy or Fields parameters, so the solution to this problem was to introduce the @db and @server special strings. But this solution is quite difficult to understand, it would be much simpler if these annotations have a query, orderBy and fields parameter by themselves, that if assigned, that information will be used in the event, and not the default information provided to the Model, permitting to separate the logic for Loading and Putting a model.

View parameters in Event

When handling (and creating) an event, the views in the layout cannot be referenced properly, for instance:

   @Event
    void onSaveProfile(TextView user_password) {
    }

This will create an event with a parameter user_password, but what is required is to pass user_password (a component in the layout) as parameter... this can be easily solved if @ViewById can be used in the parameter, something like:

   @Event
    void onSaveProfile(@ViewById TextView user_password) {
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.