Issue
I am new to Android programming, and have one question.
I am trying to access findViewById
in my AsyncTask, but obviously, by default this will not be available, because I am not performing any actions against a View object.
I have found, a few articles, explaining how to solve this, but they are old, 5 years and up, and would like to know if this is still the correct approach? I am using android's data binding methodology, and this is supposed to replace findViewById
calls, but I don't see how, in this scenario?
Is this way of solving still valid?
Here, is my code, in case there is a better solution. I am trying to access the progressbar in this view from within the AsyncTask
My Profile view:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable name="user" type="Models.User" />
<variable name="viewActions" type="ViewModel.ProfileViewModel" />
</data>
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal|top">
<ProgressBar
android:id="@+id/progressPostUser"
android:layout_width="120dp"
android:layout_height="120dp"
android:visibility="gone"/>
<include layout="@layout/main_toolbar"/>
<ImageView
android:id="@+id/imagePlaceHolder"
android:layout_width="250dp"
android:layout_height="150dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="5dp"
android:src="@mipmap/ic_account"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp">
<ImageButton
android:id="@+id/btnOpenCamera"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="10dp"
android:src="@mipmap/ic_account"
android:onClick="btnOpenCamper_OnClick"/>
<ImageButton
android:id="@+id/btnChooseImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_view_list"/>
</LinearLayout>
<EditText
android:layout_width="250dp"
android:layout_height="50dp"
android:hint="Name"
android:text="@={user._name}"/>
<EditText
android:layout_width="250dp"
android:layout_height="50dp"
android:hint="Surname"
android:text="@={user._surname}"/>
<EditText
android:layout_width="250dp"
android:layout_height="50dp"
android:hint="Email"
android:text="@={user._email}"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save"
android:onClick="@{() -> viewActions.onSaveClicked(user)}"/>
</LinearLayout>
My Activity class:
public class ProfileActivity extends MenuActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityProfileBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_profile);
binding.setUser(new User());
binding.setViewActions(new ProfileViewModel(this));
//get the toolbar
Toolbar tb = (Toolbar)findViewById(R.id.toolbarMain);
setSupportActionBar(tb);
}
}
And the 'ViewModel' which handles events from the View.
public class ProfileViewModel {
private User mUser;
private Context mContext;
public ProfileViewModel(Context context){
mContext = context;
}
public void onSaveClicked(User user) {
String nameTest = user.get_name();
String surnameTest = user.get_surname();
Toast.makeText(mContext, user.get_name(), Toast.LENGTH_SHORT).show();
}
}
Here is my User class.
public class User extends BaseObservable {
public User() {
}
private String _name;
@Bindable
public String get_name() {
return _name;
}
public void set_name(String _name) {
this._name = _name;
notifyPropertyChanged(BR._name);
}
private String _surname;
@Bindable
public String get_surname() {
return _surname;
}
public void set_surname(String _surname) {
this._surname = _surname;
notifyPropertyChanged(BR._surname);
}
private String _email;
@Bindable
public String get_email() {
return _email;
}
public void set_email(String _email) {
this._email = _email;
notifyPropertyChanged(BR._email);
}
private Bitmap _profileImage;
public Bitmap get_profileImage() {
return _profileImage;
}
public void set_profileImage(Bitmap _profileImage) {
this._profileImage = _profileImage;
}
public String toJsonString(){
try{
JSONObject jObject = new JSONObject();
jObject.put("Name", get_name());
jObject.put("Surname", get_surname());
jObject.put("Email", get_email());
jObject.put("ProfileImage", Base64.encodeToString(convertBitmapToBytes(), Base64.DEFAULT));
} catch (Exception ex){
Log.d("Error", "User.toJson");
}
return "";
}
@Override
public String toString() {
return super.toString();
}
private byte[] convertBitmapToBytes(){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
get_profileImage().compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
}
Solution
I really did not like the idea of passing context, and the View around to different objects, and like to keep the view specific functionality within the activity class itself, so I implemented an interface, that I passed around, as follow:
Here is my interface:
public interface IProfiler {
void ShowProgressbar();
void HideProgressbar();
void MakeToast();
}
My activity class implements this interface, as follow:
public class ProfileActivity extends MenuActivity implements IProfiler {
private ProgressBar mProgressar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityProfileBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_profile);
binding.setUser(new User());
binding.setViewActions(new ProfileViewModel(this));
//get the toolbar
Toolbar tb = (Toolbar)findViewById(R.id.toolbarMain);
setSupportActionBar(tb);
//set the Progressbar
mProgressar = (ProgressBar)findViewById(R.id.progressPostUser);
}
@Override
public void ShowProgressbar() {
mProgressar.setVisibility(View.VISIBLE);
}
@Override
public void HideProgressbar() {
mProgressar.setVisibility(View.GONE);
}
@Override
public void MakeToast() {
Toast.makeText(this, "Some toast", Toast.LENGTH_SHORT);
}
}
My ProfileViewModel, which excepts the interface as parameter:
public class ProfileViewModel {
private User mUser;
private IProfiler mProfiler;
public ProfileViewModel(IProfiler profiler){
mProfiler = profiler;
}
public void onSaveClicked(User user) {
try {
String nameTest = user.get_name();
String surnameTest = user.get_surname();
new AsyncTaskPost(mProfiler).execute(new URL("http://www.Trackme.com"));
}
catch (Exception ex) {
}
}
}
And then finally, my AsyncTaskPost.
public class AsyncTaskPost extends AsyncTask<URL, Void, Void> {
private IProfiler mProfilerActions;
public AsyncTaskPost(IProfiler profilerActions){
mProfilerActions = profilerActions;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mProfilerActions.ShowProgressbar();
}
@Override
protected Void doInBackground(URL... urls) {
try{
Thread.sleep(5000);
return null;
}
catch (Exception ex) {
return null;
}
}
@Override
protected void onPostExecute(Void aVoid) {
mProfilerActions.HideProgressbar();
mProfilerActions.MakeToast();
}
@Override
protected void onCancelled() {
super.onCancelled();
mProfilerActions.HideProgressbar();
}
}
Answered By - android_monstertjie
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.