【问题标题】:How to change textView properties from background thread如何从后台线程更改 textView 属性
【发布时间】:2017-02-01 15:41:54
【问题描述】:

我想更改 textView 的文本以匹配网站的标题。

为此,我连接到 https://www.google.com 并获取其 html 源代码。然后我从中获取标题标签。 (使用JSoup)

问题是现在我不知道如何更改 textView。由于网络是在后台线程中进行的,因此我无权访问它。我应该如何以及在哪里做?

另外,感谢 Log.w,我知道它已成功连接。

这是我所拥有的:

主活动

public class MainActivity extends AppCompatActivity {

    Button btnConnect;

    final String URL = "https://www.google.com";

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

        btnConnect = (Button) findViewById(R.id.btnConnect);
        btnConnect.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // launch networking task
                new EstablishConnectionTask().execute(URL);
            }
        });


    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.awakened.tirafesi.awakenedprototype.MainActivity">

    <Button
        android:text="Establish Connection"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/btnConnect" />

    <TextView
        android:text="Placeholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="87dp"
        android:id="@+id/txtTitle" />
</RelativeLayout>

建立连接任务

public class EstablishConnectionTask extends AsyncTask<String, Void, String> {


    @Override
    protected String doInBackground(String... urls) {

        String title;

        try {
            Document doc = Jsoup.connect(urls[0]).get();
            title = doc.title();

        } catch (IOException e) {
            e.printStackTrace();
            title = "NO";
        }

        return title;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        Log.w("Title", s);
    }
}

【问题讨论】:

  • 编写一个监听器并将其发送到您的 EstablishConnectionTask 然后在 onPostExecute 中调用您的接口方法。在您的 MainActivity 首先实现该侦听器并在它的覆盖方法中设置 textView 的标题。
  • 建立在@eminuluyol 所说的基础上,这个问题给出了一个代码示例:stackoverflow.com/questions/9447646/…
  • 我不明白... MainActivity 上的接口方法的覆盖将如何影响 onPostExecute 中的接口调用?你介意添加它的代码吗?
  • @Tirafesi 查看我发布的答案

标签: android android-asynctask jsoup


【解决方案1】:

onCreate() 中初始化TextView,就像为Button 所做的一样。使用 Constructor 类将 textView 传递给 Asynctask

完整的求解代码:

public class MainActivity extends AppCompatActivity {

Button btnConnect;
TextView textView;

final String URL = "https://www.google.com";

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

    textView = (TextView) findViewById(R.id.txtTitle);
    btnConnect = (Button) findViewById(R.id.btnConnect);
    btnConnect.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

            //pass TextView of this class to Asynctask cass
            new EstablishConnectionTask(textView).execute(URL);
        }
    });
  }
}

异步任务类:

public class EstablishConnectionTask extends AsyncTask<String, Void, String> {

public TextView textView;

//constructor to pass textView
public EstablishConnectionTask(TextView textView){
    this.textView = textView;
}

@Override
protected String doInBackground(String... urls) {

    String title;
    try {
        Document doc = Jsoup.connect(urls[0]).get();
        title = doc.title();

    } catch (IOException e) {
        e.printStackTrace();
        title = "NO";
    }
    return title;
}

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    textView.setText(s); // add title to textView

    Log.w("Title", s);
 }
}

【讨论】:

    【解决方案2】:

    这个问题告诉你如何解决你的问题:how do i send data back from onPostExecute in an AsyncTask?

    在调用activity的doStuff()接口方法中更改TextView。

    【讨论】:

      【解决方案3】:

      我假设您想知道如何从 doInBackground() 方法或后台线程访问或更改 UI 组件,提供 AsyncTask 或 .为此,您使用处理程序。例如在 AsyncTask 类中初始化一个 Handler 的对象 现在在 doInBackground() 方法或线程的 Run() 方法中调用方法 handler.post() ,如下所示

      Handler handler = new Handler();
      handler.post(new Runnable{
       @overide
       public void run(){
        textView.setText("Changed");
       }
      });
      

      记得在 doInBackground() 或 run() 方法之外初始化处理程序;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-28
        相关资源
        最近更新 更多