xml AppDatabase.java

AppDatabase.java

@Database(entities = {Note.class}, version = 1, exportSchema = true)
public abstract class AppDatabase extends RoomDatabase {
    private static AppDatabase appDatabase;

    public abstract NoteDao noteDao();

    public static AppDatabase getInstance(Context context){
        if (appDatabase==null){
            appDatabase= Room.databaseBuilder(context,AppDatabase.class,"db_7learn").allowMainThreadQueries().build();
        }
        return appDatabase;
    }
}
AppSetting.java

public class AppSetting {
    private SharedPreferences sharedPreferences;
    private static final String KEY_FIRST_NAME = "first_name";
    private static final String KEY_LAST_NAME = "last_name";
    private static final String KEY_AGE = "age";
    private static final String KEY_RATE = "rate";

    public AppSetting(Context context) {
        sharedPreferences = context.getSharedPreferences("setting", Context.MODE_PRIVATE);
    }


    public void saveUserInfo(String firstName, String lastName, int age, float rate) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(KEY_FIRST_NAME, firstName);
        editor.putString(KEY_LAST_NAME, lastName);
        editor.putInt(KEY_AGE, age);
        editor.putFloat(KEY_RATE, rate);
        editor.apply();
    }


    public String getFirstName() {
        return sharedPreferences.getString(KEY_FIRST_NAME, "");
    }

    public String getLastName() {
        return sharedPreferences.getString(KEY_LAST_NAME, "");
    }

    public int getAge() {
        return sharedPreferences.getInt(KEY_AGE, 0);
    }

    public float getRate() {
        return sharedPreferences.getFloat(KEY_RATE, 0);
    }
}
EditNoteDialog.java

public class EditNoteDialog extends DialogFragment {
    private OnNoteEdit onNoteEdit;
    private Note note;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null)
            note = getArguments().getParcelable("note");
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnNoteEdit) {
            onNoteEdit = (OnNoteEdit) context;
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_edit_note, null);
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setView(view);
        final EditText titleEt = view.findViewById(R.id.et_editNote_title);
        final EditText descEt = view.findViewById(R.id.et_editNote_desc);
        if (note != null) {
            titleEt.setText(note.getTitle());
            descEt.setText(note.getDescripion());
        }
        Button saveNoteBtn = view.findViewById(R.id.btn_editNote_save);
        saveNoteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (titleEt.length() > 0 && descEt.length() > 0) {

                    if (note != null) {
                        note.setTitle(titleEt.getText().toString());
                        note.setDescripion(descEt.getText().toString());
                        onNoteEdit.onEdit(note);
                    } else {
                        Note note = new Note();
                        note.setTitle(titleEt.getText().toString());
                        note.setDescripion(descEt.getText().toString());
                        onNoteEdit.onEdit(note);
                    }
                    dismiss();

                }
            }
        });
        return builder.create();
    }

    public static EditNoteDialog newInstance(Note note) {

        Bundle args = new Bundle();
        args.putParcelable("note", note);
        EditNoteDialog fragment = new EditNoteDialog();
        fragment.setArguments(args);
        return fragment;
    }

    public interface OnNoteEdit {
        void onEdit(Note note);
    }
}
MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_main_sharedPref:
                startActivity(new Intent(MainActivity.this, PersonalInfoActivity.class));
                break;
            case R.id.btn_main_room:
                startActivity(new Intent(MainActivity.this, NotesActivity.class));
                break;
        }
    }
}
NoteAdapter.java

public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteViewHolder> {
    private NoteUiCallback noteUiCallback;
    private List<Note> notes = new ArrayList<>();

    public NoteAdapter(NoteUiCallback noteUiCallback) {
        this.noteUiCallback = noteUiCallback;
    }

    public void addNotes(List<Note> notes) {
        this.notes.addAll(notes);
        notifyDataSetChanged();
    }

    public void addNote(Note note) {
        this.notes.add(0, note);
        notifyItemInserted(0);
    }

    public void clear(){
        this.notes.clear();
        notifyDataSetChanged();
    }

    public void updateNote(Note note) {
        for (int i = 0; i < notes.size(); i++) {
            if (notes.get(i).getId() == note.getId()) {
                notes.set(i, note);
                notifyItemChanged(i);
                return;
            }
        }
    }


    @NonNull
    @Override
    public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new NoteViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_note, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull NoteViewHolder noteViewHolder, int i) {
        noteViewHolder.bindNote(notes.get(i));
    }

    @Override
    public int getItemCount() {
        return notes.size();
    }

    public class NoteViewHolder extends RecyclerView.ViewHolder {
        private TextView titleTv;
        private TextView descTv;
        private Button deleteButton;
        private Button editButton;

        public NoteViewHolder(@NonNull View itemView) {
            super(itemView);
            titleTv = itemView.findViewById(R.id.tv_note_title);
            descTv = itemView.findViewById(R.id.tv_note_desc);
            deleteButton = itemView.findViewById(R.id.btn_note_delete);
            editButton = itemView.findViewById(R.id.btn_note_edit);
        }

        public void bindNote(final Note note) {
            titleTv.setText(note.getTitle());
            descTv.setText(note.getDescripion());
            deleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    noteUiCallback.onDeleteBtnClick(note, getAdapterPosition());
                }
            });
            editButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    noteUiCallback.onEditBtnClick(note, getAdapterPosition());
                }
            });
        }
    }

    public void deleteNote(int position) {
        notes.remove(position);
        notifyItemRemoved(position);
    }

    public interface NoteUiCallback {
        void onDeleteBtnClick(Note note, int position);

        void onEditBtnClick(Note note, int position);
    }
}
NotesActivity.java

public class NotesActivity extends AppCompatActivity implements EditNoteDialog.OnNoteEdit, NoteAdapter.NoteUiCallback {
    private NoteDao noteDao;
    private NoteAdapter noteAdapter;
    private boolean isInEditMode = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notes);
        AppDatabase appDatabase = AppDatabase.getInstance(this);
        noteDao = appDatabase.noteDao();
        List<Note> notes = noteDao.getAll();
        RecyclerView recyclerView = findViewById(R.id.rv_notes);
        recyclerView.setLayoutManager(new LinearLayoutManager(
                this, LinearLayoutManager.VERTICAL, false
        ));
        noteAdapter = new NoteAdapter(this);
        recyclerView.setAdapter(noteAdapter);
        noteAdapter.addNotes(notes);

        Button addNoteBtn = findViewById(R.id.btn_notes_addNewNote);
        addNoteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isInEditMode = false;
                EditNoteDialog dialog = new EditNoteDialog();
                dialog.show(getSupportFragmentManager(), null);
            }
        });


        Button deleteBtn = findViewById(R.id.btn_notes_deleteAll);
        deleteBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                noteDao.deleteAll();
                noteAdapter.clear();
            }
        });
    }

    @Override
    public void onEdit(Note note) {
        if (isInEditMode) {
            noteDao.update(note);
            noteAdapter.updateNote(note);
        } else {
            noteDao.save(note);
            noteAdapter.addNote(note);
        }

    }

    @Override
    public void onDeleteBtnClick(Note note, int position) {
        noteDao.delete(note);
        noteAdapter.deleteNote(position);
    }

    @Override
    public void onEditBtnClick(Note note, int position) {
        isInEditMode = true;
        EditNoteDialog editNoteDialog = EditNoteDialog.newInstance(note);
        editNoteDialog.show(getSupportFragmentManager(), null);
    }
}
PersonalInfoActivity.java

public class PersonalInfoActivity extends AppCompatActivity {
    private AppSetting setting;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_personal_info);
        setting = new AppSetting(this);
        final EditText firstNameEt = findViewById(R.id.et_main_firstName);
        final EditText lastNameEt = findViewById(R.id.et_main_lastName);
        final EditText ageEt = findViewById(R.id.et_main_age);
        final EditText rateEt = findViewById(R.id.et_main_rate);

        Button saveBtn = findViewById(R.id.btn_main_save);
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setting.saveUserInfo(firstNameEt.getText().toString(),
                        lastNameEt.getText().toString(),
                        Integer.parseInt(ageEt.getText().toString()),
                        Float.parseFloat(rateEt.getText().toString()));
            }
        });

        firstNameEt.setText(setting.getFirstName());
        lastNameEt.setText(setting.getLastName());
        ageEt.setText(String.valueOf(setting.getAge()));
        rateEt.setText(String.valueOf(setting.getRate()));
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn_main_sharedPref"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Shared Pref"
        android:onClick="onClick" />

    <Button
        android:id="@+id/btn_main_room"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Room"
        android:onClick="onClick" />
    <Button
        android:id="@+id/btn_main_broadcastReceiver"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Broadcast Receiver"
        android:onClick="onClick" />

</LinearLayout>
activity_notes.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".notes.NotesActivity">

    <Button
        android:id="@+id/btn_notes_addNewNote"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Add new note" />

    <Button
        android:id="@+id/btn_notes_deleteAll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/btn_notes_addNewNote"
        android:text="Delete All" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_notes"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/btn_notes_deleteAll">

    </android.support.v7.widget.RecyclerView>
</RelativeLayout>
activity_personal_info.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".sharedpref.PersonalInfoActivity">

    <EditText
        android:id="@+id/et_main_firstName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="First Name" />

    <EditText
        android:id="@+id/et_main_lastName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Last Name" />

    <EditText
        android:id="@+id/et_main_age"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Age" />

    <EditText
        android:id="@+id/et_main_rate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Rate" />

    <Button
        android:id="@+id/btn_main_save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Save" />


</LinearLayout>
build.gradle.app



    def room_version = "1.1.1"

    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"
    implementation 'com.android.support:recyclerview-v7:28.0.0'
dialog_edit_note.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:id="@+id/et_editNote_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter title"/>

    <EditText
        android:id="@+id/et_editNote_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter description"/>

    <Button
        android:id="@+id/btn_editNote_save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Save"/>
</LinearLayout>
item_note.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_note_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black" />

    <TextView
        android:id="@+id/tv_note_desc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_note_edit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Edit"/>

        <Button
            android:id="@+id/btn_note_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Delete"/>
    </LinearLayout>
</LinearLayout>

xml ApiService.java

ApiService.java

public class ApiService {

    private Context context;
    private RequestQueue requestQueue;

    public ApiService(Context context) {

        this.context = context;
        requestQueue = Volley.newRequestQueue(context);
    }

    public void registerStudent(String firstName, String lastName, String course, int score, Response.Listener<Student> listener, Response.ErrorListener errorListener){

        GsonRequest<Student> request = new GsonRequest<>(Request.Method.POST
                , "experts/student",
                new TypeToken<Student>() {
                }.getType(),
                listener,
                errorListener);
        JsonObject jsonObject=new JsonObject();
        jsonObject.addProperty("first_name",firstName);
        jsonObject.addProperty("last_name",lastName);
        jsonObject.addProperty("course",course);
        jsonObject.addProperty("score",score);
        request.setJsonObject(jsonObject);
        requestQueue.add(request);

    }

    public void listStudents(Response.Listener<List<Student>> listener, Response.ErrorListener errorListener) {
        GsonRequest<List<Student>> request = new GsonRequest<>(Request.Method.GET
                , "experts/student",
                new TypeToken<List<Student>>() {
                }.getType(),
                listener,
                errorListener);
        requestQueue.add(request);
    }
}
Bulid.gradle
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    
    
    
    AndroidManifest.xml
    <uses-permission android:name="android.permission.INTERNET" />
GsonRequest.java
package com.sevenlearn.studentexample;

import android.support.annotation.Nullable;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import org.json.JSONObject;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GsonRequest<T> extends Request<T> {
    private Response.Listener<T> listener;
    private Type type;
    private JsonObject jsonObject;

    public GsonRequest(int method, String url, Type type, Response.Listener<T> listener, @Nullable Response.ErrorListener errorListener) {
        super(method, "http://expertdevelopers.ir/api/v1/"+url, errorListener);
        this.listener = listener;
        this.type = type;
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            String responseStr = new String(response.data);
            Gson gson = new Gson();
            T result = gson.fromJson(responseStr, type);
            return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
        } catch (Exception e) {
            return Response.error(new VolleyError(e));
        }

    }

    @Override
    protected void deliverResponse(T response) {
        listener.onResponse(response);
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        if (jsonObject!=null)
            return jsonObject.toString().getBytes();
        return super.getBody();
    }

    @Override
    public String getBodyContentType() {
        return "application/json";
    }

    public void setJsonObject(JsonObject jsonObject) {
        this.jsonObject = jsonObject;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String,String> map=new HashMap<>();
        map.put("Accept-Language","fa-IR");
        map.put("Accept","application/json");
        return map;
    }
}
MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private ApiService apiService;
    private StudentAdapter studentAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        apiService = new ApiService(this);
        Button registerStudent = findViewById(R.id.btn_main_registerStudent);
        final EditText firstNameEt = findViewById(R.id.et_main_firstName);
        final EditText lastNameEt = findViewById(R.id.et_main_lastName);
        final EditText courseEt = findViewById(R.id.et_main_course);
        final EditText scoreEt = findViewById(R.id.et_main_score);
        final RecyclerView recyclerView=findViewById(R.id.rv_main_students);

        recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
        studentAdapter=new StudentAdapter();
        recyclerView.setAdapter(studentAdapter);
        registerStudent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                apiService.registerStudent(firstNameEt.getText().toString(), lastNameEt.getText().toString(), courseEt.getText().toString(), Integer.parseInt(scoreEt.getText().toString()),student -> {
                            studentAdapter.addStudent(student);
                            recyclerView.smoothScrollToPosition(studentAdapter.getItemCount()-1);
                            Log.i(TAG, "onResponse: ");
                        },
                        new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                Log.e(TAG, "onErrorResponse: ", error);
                            }
                        });
            }
        });

        apiService.listStudents(new Response.Listener<List<Student>>() {
            @Override
            public void onResponse(List<Student> response) {
                Log.i(TAG, "onResponse: ");
                studentAdapter.setStudents(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "onErrorResponse: ", error);
            }
        });
    }
}
Student.java


@SuppressWarnings("unused")
public class Student {

    @Expose
    private String course;
    @SerializedName("created_at")
    private String createdAt;
    @SerializedName("first_name")
    private String firstName;
    @Expose
    private Long id;
    @SerializedName("last_name")
    private String lastName;
    @Expose
    private Long score;
    @SerializedName("updated_at")
    private String updatedAt;

    public String getCourse() {
        return course;
    }

    public void setCourse(String course) {
        this.course = course;
    }

    public String getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(String createdAt) {
        this.createdAt = createdAt;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Long getScore() {
        return score;
    }

    public void setScore(Long score) {
        this.score = score;
    }

    public String getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(String updatedAt) {
        this.updatedAt = updatedAt;
    }

}
StudentAdapter.java

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
    private List<Student> students = new ArrayList<>();

    public StudentAdapter() {

    }

    public void setStudents(List<Student> students) {
        this.students = students;
        notifyDataSetChanged();
    }

    public void addStudent(Student student) {
        this.students.add(student);
        notifyItemInserted(students.size()-1);
    }

    @NonNull
    @Override
    public StudentViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new StudentViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(
                R.layout.item_student, viewGroup, false
        ));
    }

    @Override
    public void onBindViewHolder(@NonNull StudentViewHolder studentViewHolder, int i) {
        studentViewHolder.bindStudent(students.get(i));
    }

    @Override
    public int getItemCount() {
        return students.size();
    }

    public class StudentViewHolder extends RecyclerView.ViewHolder {
        private TextView firstNameTv;
        private TextView lastNameTv;
        private TextView courseTv;
        private TextView scoreTv;

        public StudentViewHolder(@NonNull View itemView) {
            super(itemView);
            firstNameTv = itemView.findViewById(R.id.tv_student_firstName);
            lastNameTv = itemView.findViewById(R.id.tv_student_lastName);
            courseTv = itemView.findViewById(R.id.tv_student_course);
            scoreTv = itemView.findViewById(R.id.tv_student_score);
        }

        public void bindStudent(Student student) {
            firstNameTv.setText(student.getFirstName());
            lastNameTv.setText(student.getLastName());
            courseTv.setText(student.getCourse());
            scoreTv.setText(itemView.getContext().getString(R.string.scorePlaceHolder, student.getScore()));
        }
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/et_main_firstName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="First name" />

    <EditText
        android:id="@+id/et_main_lastName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Last name" />

    <EditText
        android:id="@+id/et_main_course"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Course" />

    <EditText
        android:id="@+id/et_main_score"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Score" />

    <Button
        android:id="@+id/btn_main_registerStudent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Register Student" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_main_students"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>
</LinearLayout>
item_student.xml
<?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="wrap_content">
    <TextView
        android:id="@+id/tv_student_firstName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="@android:color/black"
        tools:text="FirstName"/>

    <TextView
        android:id="@+id/tv_student_lastName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="@android:color/black"
        tools:text="LastName"/>

    <TextView
        android:id="@+id/tv_student_course"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="@android:color/black"
        tools:text="Course"/>

    <TextView
        android:id="@+id/tv_student_score"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="@android:color/black"
        tools:text="Score"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="8dp"
        android:background="#ddd"/>
</LinearLayout>
strings.xml
<resources>
    <string name="app_name">StudentExample</string>
    <string name="scorePlaceHolder">Score: %1$d</string>
</resources>

xml 使用apche poi,xdocreport和itext扩展将Docx转换为PDF

Converter.java
/**
     * convert to pdf using xdocreport, apache poi and itext extension
     * note: not compatible with RTL languages
     */
    public static void ConvertToPDFUsingXDocAndPoiAndItext(String docPath, String pdfPath) {
        try {
            InputStream doc = new FileInputStream(new File(docPath));
            XWPFDocument document = new XWPFDocument(doc);
            PdfOptions options = PdfOptions.create();
            OutputStream out = new FileOutputStream(new File(pdfPath));
            PdfConverter.getInstance().convert(document, out, options);
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
    
  // convert docx to pdf using apache poi
  // note: RTL Languages are not supported
  public byte[] getPDFByXWPF() {
        try {
            XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(file.toByteArray()));
            PdfOptions options = PdfOptions.create();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            PdfConverter.getInstance().convert(document, outputStream, options);
            return outputStream.toByteArray();
        }catch (IOException e){
            return null;
        }
    }
pom.xml
        <!-- Note: not sure if these are all of the dependencies --> 
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.itext.extension</artifactId>
            <version>2.0.2</version>
        </dependency>

        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>org.apache.poi.xwpf.converter.core</artifactId>
            <version>1.0.6</version>
        </dependency>
        
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
            <version>1.0.6</version>
        </dependency>

xml 使用document4j将Docx转换为PDF

Document4jUtil.java
/**
     * convert to pdf using document4j
     * RTL languages are supported
     */
    public static void convertUsingDocument4j(){
        File inputWord = new File("E:/1.docx");
        File outputFile = new File("E:/Test_out.pdf");
        try  {
            InputStream docxInputStream = new FileInputStream(inputWord);
            OutputStream outputStream = new FileOutputStream(outputFile);
            IConverter converter = LocalConverter.builder().build();
            converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
            outputStream.close();
            System.out.println("success");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
pom.xml
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-local</artifactId>
            <version>1.0.3</version>
        </dependency>
        
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-transformer-msoffice-word</artifactId>
            <version>1.0.3</version>
        </dependency>

xml android_remove_toolbar.xml

android_remove_toolbar.xml
    <!-- styles.xml -->
  
  <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionModeOverlay">true</item>
    </style>

 <!-- manifest.xml -->
<activity android:name=".MainActivity"
            android:theme="@style/AppTheme.NoActionBar">
        </activity>

xml 改造实例

gradle dependancies
implementation com.squareup.retrofit2:converter-gson
implementation 'com.squareup.retrofit2:retrofit:(insert latest version)'
Post
package com.codinginflow.retrofitexample;
 
import com.google.gson.annotations.SerializedName;
 
public class Post {
 
    private int userId;
 
    private int id;
 
    private String title;
 
 //if name is different from wanted title
    @SerializedName("body")
    private String text;
 
    public int getUserId() {
        return userId;
    }
 
    public int getId() {
        return id;
    }
 
    public String getTitle() {
        return title;
    }
 
    public String getText() {
        return text;
    }
}
JsonAPI
package com.codinginflow.retrofitexample;
 
import java.util.List;
 
import retrofit2.Call;
import retrofit2.http.GET;
 
public interface JsonPlaceHolderApi {
 
    @GET("posts")
    Call<List<Post>> getPosts();
    
    @GET("posts")
    Call<List<Post>> getPosts(@QueryMap Map<String, String> parameters);
 
    @GET("posts/{id}/comments")
    Call<List<Comment>> getComments(@Path("id") int postId);
 
    @GET
    Call<List<Comment>> getComments(@Url String url);
    
        @POST("posts")
    Call<Post> createPost(@Body Post post);
 
    @FormUrlEncoded
    @POST("posts")
    Call<Post> createPost(
            @Field("userId") int userId,
            @Field("title") String title,
            @Field("body") String text
    );
 
    @FormUrlEncoded
    @POST("posts")
    Call<Post> createPost(@FieldMap Map<String, String> fields);
}
MainActivity
package com.codinginflow.retrofitexample;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
 
import java.util.List;
 
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
 
public class MainActivity extends AppCompatActivity {
    private TextView textViewResult;
 
    private JsonPlaceHolderApi jsonPlaceHolderApi;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textViewResult = findViewById(R.id.text_view_result);
 
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://jsonplaceholder.typicode.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
 
        jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
 
        //getPosts();
        //getComments();
        createPost();
    }
 
    private void getPosts() {
        Map<String, String> parameters = new HashMap<>();
        parameters.put("userId", "1");
        parameters.put("_sort", "id");
        parameters.put("_order", "desc");
 
        Call<List<Post>> call = jsonPlaceHolderApi.getPosts(parameters);
 
        call.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
 
                if (!response.isSuccessful()) {
                    textViewResult.setText("Code: " + response.code());
                    return;
                }
 
                List<Post> posts = response.body();
 
                for (Post post : posts) {
                    String content = "";
                    content += "ID: " + post.getId() + "\n";
                    content += "User ID: " + post.getUserId() + "\n";
                    content += "Title: " + post.getTitle() + "\n";
                    content += "Text: " + post.getText() + "\n\n";
 
                    textViewResult.append(content);
                }
            }
 
            @Override
            public void onFailure(Call<List<Post>> call, Throwable t) {
                textViewResult.setText(t.getMessage());
            }
        });
    }
 
    private void getComments() {
        Call<List<Comment>> call = jsonPlaceHolderApi
                .getComments("https://jsonplaceholder.typicode.com/posts/3/comments");
 
        call.enqueue(new Callback<List<Comment>>() {
            @Override
            public void onResponse(Call<List<Comment>> call, Response<List<Comment>> response) {
 
                if (!response.isSuccessful()) {
                    textViewResult.setText("Code: " + response.code());
                    return;
                }
 
                List<Comment> comments = response.body();
 
                for (Comment comment : comments) {
                    String content = "";
                    content += "ID: " + comment.getId() + "\n";
                    content += "Post ID: " + comment.getPostId() + "\n";
                    content += "Name: " + comment.getName() + "\n";
                    content += "Email: " + comment.getEmail() + "\n";
                    content += "Text: " + comment.getText() + "\n\n";
 
                    textViewResult.append(content);
                }
            }
 
            @Override
            public void onFailure(Call<List<Comment>> call, Throwable t) {
                textViewResult.setText(t.getMessage());
            }
        });
    }
 
    private void createPost() {
        Post post = new Post(23, "New Title", "New Text");
 
        Map<String, String> fields = new HashMap<>();
        fields.put("userId", "25");
        fields.put("title", "New Title");
 
        Call<Post> call = jsonPlaceHolderApi.createPost(fields);
 
        call.enqueue(new Callback<Post>() {
            @Override
            public void onResponse(Call<Post> call, Response<Post> response) {
 
                if (!response.isSuccessful()) {
                    textViewResult.setText("Code: " + response.code());
                    return;
                }
 
                Post postResponse = response.body();
 
                String content = "";
                content += "Code: " + response.code() + "\n";
                content += "ID: " + postResponse.getId() + "\n";
                content += "User ID: " + postResponse.getUserId() + "\n";
                content += "Title: " + postResponse.getTitle() + "\n";
                content += "Text: " + postResponse.getText() + "\n\n";
 
                textViewResult.setText(content);
            }
 
            @Override
            public void onFailure(Call<Post> call, Throwable t) {
                textViewResult.setText(t.getMessage());
            }
        });
    }
}
Manifest
<uses-permission android:name="android.permission.INTERNET" />

xml maven tomcat插件

pom.xml
      <plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.2</version>
				<configuration>
					<!--端口控制-->
					<port>8080</port>
					<!--项目路径控制意味着http://localhost:8080/abc-->
					<path>/abc</path>
					<!--编码-->
					<uriEncoding>UTF-8</uriEncoding>
				</configuration>
			</plugin

xml RecyclerView

MainActivity.java
package com.sevenlearn.recyclerviewsample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final RecyclerView recyclerView = findViewById(R.id.rv_main_contacts);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

        List<Contact> contacts = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            Contact contact = new Contact();
            contact.setName("Name " + (i + 1));
            contact.setPhoneNumber("PhoneNumber " + (i + 1));
            contacts.add(contact);
        }

        final ContactAdapter contactAdapter = new ContactAdapter(this, contacts);
        recyclerView.setAdapter(contactAdapter);

        final EditText nameEt = findViewById(R.id.et_main_name);
        final EditText phoneNumberEt = findViewById(R.id.et_main_phoneNumber);
        Button addContactBtn = findViewById(R.id.btn_main_addContact);
        
        
        addContactBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Contact contact = new Contact();
                contact.setName(nameEt.getText().toString());
                contact.setPhoneNumber(phoneNumberEt.getText().toString());
                contactAdapter.addContact(contact);
                recyclerView.smoothScrollToPosition(0);
            }
        });
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/ll_main_addNewContactContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:orientation="vertical">

        <EditText
            android:id="@+id/et_main_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter Contact Name Here..." />

        <EditText
            android:id="@+id/et_main_phoneNumber"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter Phone Number Here..." />

        <Button
            android:id="@+id/btn_main_addContact"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/blue500"
            android:text="Add to list"
            android:textColor="@android:color/white" />
    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_main_contacts"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/ll_main_addNewContactContainer">

    </android.support.v7.widget.RecyclerView>
</RelativeLayout>
Contact.java
package com.sevenlearn.recyclerviewsample;

public class Contact {
    private String name;
    private String phoneNumber;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}
implementation
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.sevenlearn.recyclerviewsample"
        minSdkVersion 17
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
}
ContactAdapter.java
package com.sevenlearn.recyclerviewsample;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.List;

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {
    private static final String TAG = "ContactAdapter";
    private List<Contact> contacts = new ArrayList<>();
    private Context context;

    public ContactAdapter(Context context, List<Contact> contacts) {
        this.context = context;
        this.contacts = contacts;
    }

    public void addContact(Contact contact) {
        this.contacts.add(0, contact);
        notifyItemInserted(0);
    }

    @NonNull
    @Override
    public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_contact, viewGroup, false);
        Log.i(TAG, "onCreateViewHolder is called ");
        return new ContactViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ContactViewHolder contactViewHolder, int position) {
        Log.i(TAG, "onBindViewHolder is called, position=>  " + position);
        contactViewHolder.bindContact(contacts.get(position));
    }

    @Override
    public int getItemCount() {
        return contacts.size();
    }

    public class ContactViewHolder extends RecyclerView.ViewHolder {
        private TextView firstCharacterTv;
        private TextView nameTv;
        private TextView phoneNumberTv;
        private View deleteButton;

        public ContactViewHolder(@NonNull View itemView) {
            super(itemView);
            firstCharacterTv = itemView.findViewById(R.id.tv_contact_firstChar);
            nameTv = itemView.findViewById(R.id.tv_contact_name);
            phoneNumberTv = itemView.findViewById(R.id.tv_contact_phoneNumber);
            deleteButton = itemView.findViewById(R.id.iv_contact_delete);
        }

        public void bindContact(Contact contact) {
            firstCharacterTv.setText(contact.getName().substring(0, 1));
            nameTv.setText(contact.getName());
            phoneNumberTv.setText(contact.getPhoneNumber());
            deleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    contacts.remove(getAdapterPosition());
                    notifyItemRemoved(getAdapterPosition());
                }
            });
        }
    }
}
item_contact.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_contact_firstChar"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@drawable/background_contact_first_char"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="16dp"
        android:gravity="center"
        android:textSize="24sp"
        android:textColor="@android:color/white"
        android:text="A" />

    <ImageView
        android:id="@+id/iv_contact_delete"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="16dp"
        android:src="@drawable/ic_action_delete"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toStartOf="@id/iv_contact_delete"
        android:layout_marginStart="8dp"
        android:layout_toEndOf="@id/tv_contact_firstChar"
        android:layout_centerVertical="true"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_contact_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@android:color/black"
            android:text="Ali Ahmadi"/>
        <TextView
            android:id="@+id/tv_contact_phoneNumber"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:text="09378122153"/>
    </LinearLayout>
</RelativeLayout>
ic_action_delete.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="#333333">
    <path
        android:fillColor="#FF000000"
        android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

xml ehcache配置

ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache> 
  <diskStore path="java.io.tmpdir"/> 
  <defaultCache 
     maxEntriesLocalHeap="10000" 
     eternal="false" 
     timeToIdleSeconds="120" 
     timeToLiveSeconds="120" 
     maxEntriesLocalDisk="10000000" 
     diskExpiryThreadIntervalSeconds="120" 
     memoryStoreEvictionPolicy="LRU"> 
     <persistence strategy="localTempSwap"/> 
  </defaultCache> 
</ehcache>

xml java.lang.OutOfMemoryError

java.lang.OutOfMemoryError
android:hardwareAccelerated="false"

android:largeHeap="true"