【问题标题】:Passing view to AsyncTask to access findViewById将视图传递给 AsyncTask 以访问 findViewById
【发布时间】:2018-02-08 18:38:42
【问题描述】:

我是 Android 编程新手,有一个问题。

我试图在我的 AsyncTask 中访问 findViewById,但显然默认情况下这将不可用,因为我没有对 View 对象执行任何操作。

我找到了几篇文章,解释了如何解决这个问题,但它们已经老了,5 年以上,想知道这是否仍然是正确的方法?我正在使用 android 的数据绑定方法,这应该替换 findViewById 调用,但我不知道在这种情况下如何?

this的解决方式还有效吗?

这是我的代码,以防有更好的解决方案。我正在尝试从 AsyncTask

中访问此视图中的进度条

我的个人资料视图:

<?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>

我的活动课:

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);
}
}

以及处理来自视图的事件的“ViewModel”。

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();
}
}

这是我的用户类。

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();
}

}

【问题讨论】:

  • 您可以在 onCreate 上实例化视图,然后在异步中访问它。我做到了,效果很好。
  • @DroiDev 你的意思和我提到的文章中描述的一样吗?
  • 添加您的模型以获得更清晰的视图
  • @android_monstertjie 我没看过。
  • @JoshuaUchennaAmaju 添加了模型类

标签: java android android-studio android-asynctask


【解决方案1】:

你可以做这样的事情。您可以更改 onPre、doInBackground、onPost 中的信息 --> 这无关紧要。

public class MainActivity extends AppCompatActivity {

    TestView textView;

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

    }


    private class ASyncCall extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //What happens BEFORE everything in the background.
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            textView.setText("set the text");
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            //After you get everything you need from the JSON.

        }
    }
}

【讨论】:

  • 这种方法根本没有考虑我到目前为止所拥有的东西?还是我在这里弄错了/
  • 我也可能会误会您的问题。 findViewById 与视图上的 ID 有关......对吗?您想访问异步内部的视图吗?
  • 正确,但是将调用 AsyncTask 类的调用代码不在我的活动类中。我的 onSaveClicked 函数是在用户单击保存按钮时调用的,它是在 ProfileViewModel 类中定义的,而不是在活动类中定义的
  • 我赞成你的回答,因为我仍然从中学到了一些东西,在课堂上声明了一个班级;-)
  • 你不能真正做到这一点。 findviewbyid 必须在调用布局的地方调用。你应该在活动中拥有你的 aynsc,并调用你可以调用异步内部的方法以获得你需要的东西。
【解决方案2】:

我真的不喜欢将上下文和视图传递给不同对象的想法,并且喜欢将视图特定功能保留在活动类本身中,所以我实现了一个接口,我传递了如下:

这是我的界面:

public interface IProfiler {
    void ShowProgressbar();
    void HideProgressbar();
    void MakeToast();
}

我的activity类实现了这个接口,如下:

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);
}
}

我的ProfileViewModel,除了接口作为参数:

    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) {

        }
    }
}

最后,我的 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();
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多