简体   繁体   English

从服务中的活动引用文本视图,反之亦然

[英]Referencing TextViews from Activity in Service and Vice versa

I am working on an Android app with a steadily growing Code basis;我正在开发一个 Android 应用程序,其代码基础稳步增长; the aim of the app is to scan and process QR Codes and Barcodes on Handheld Devices for Storages (not Smartphones).该应用程序的目的是扫描和处理手持设备(不是智能手机)上的二维码和条形码。 It hast two Activities that contain major parts of the programmatical logic;它有两个包含程序逻辑主要部分的活动; hence, I want to store major parts of the Code that contains the Functionality for processing the Scanner input in an external Service, called Scanner Service, implement the methods there and use the methods in other Activites;因此,我想将包含用于处理扫描仪输入的功能的代码的主要部分存储在称为扫描仪服务的外部服务中,在那里实现方法并在其他活动中使用这些方法;

however, I have a major issue with the use of Context, getApplicationContext() and the reference of the Activity in the Service and vice versa;但是,我在使用 Context、getApplicationContext() 和服务中的 Activity 引用时遇到了一个主要问题,反之亦然; although I think I have referenced and initialised the Textviews from the Activity in the Service, the app keeps on crashing with the following error message:尽管我认为我已经从服务中的 Activity 中引用并初始化了 Textviews,但该应用程序继续崩溃并显示以下错误消息:

AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Activity.findViewById(int)' on a null object reference
        at com.xxxx.ScanService.<clinit>(ScanService.java:16)

I know what it means, but I don´t know how I could access the View我知道这意味着什么,但我不知道如何访问视图

private static TextView content = (TextView) a.findViewById(R.id.content_detail);

in such a way that I can use it in the Service and in the Activity and the app stops crashing.这样我就可以在服务和活动中使用它,并且应用程序停止崩溃。

Therefore, any hints or help would be very much appreciated, thank you in advance.因此,任何提示或帮助将不胜感激,在此先感谢您。

The MainDetailActivity: MainDetailActivity:

package com.example.xxx_app;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.RecyclerView;
import android.view.MenuItem;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.xxx.ScanService.*;
import static com.xxx.SimpleItemRecyclerViewAdapter.TAGG;

/**
 * An activity representing a single Main detail screen. This
 * activity is only used on narrow width devices. On tablet-size devices,
 * item details are presented side-by-side with a list of items
 * in a {@link MainListActivity}.
 */
public class MainDetailActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener,
        PopupMenu.OnMenuItemClickListener {
    Context context;
    private RecyclerView recyclerView;
    private RecyclerviewAdapter recyclerviewAdapter;
    private RecyclerTouchListener touchListener;
    private ListView listView;
    public TextView textView4;
    public String code;
    public static final String TAG = "Barcode ist:" ;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_detail);
        context = this;
        //TextView headerView = findViewById(R.id.txt1);
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        EditText editBarcode = (EditText) findViewById(R.id.editText);
        TextView content = (TextView) findViewById(R.id.content_detail);
        TextView editTextNumber = findViewById(R.id.editTextNumber);
        Button addBooking = findViewById(R.id.button);
        Button removeBooking = findViewById(R.id.button2);
        removeBooking.setEnabled(false);
        spinner.setOnItemSelectedListener(this);

        //String selectedItem = spinner.getSelectedItem().toString();
        // Create an ArrayAdapter using the string array and a default spinner layout
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
                R.array.mockdata, android.R.layout.simple_spinner_item);
        // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        // Apply the adapter to the spinner
        spinner.setAdapter(adapter);
        String scannedCode = getIntent().getStringExtra("scannedCode");
        Log.d(TAG, "scannedCode" + scannedCode);
        if (scannedCode != null && (content.getText().toString().equals(""))) {
          content.setText(scannedCode);
        }


        Button btn = findViewById(R.id.imageView4);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PopupMenu popup = new PopupMenu(MainDetailActivity.this, v);
                popup.setOnMenuItemClickListener(MainDetailActivity.this);
                popup.inflate(R.menu.popup_menu);
                popup.show();
            }
        });

        editBarcode.setOnKeyListener(new View.OnKeyListener() {

            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {

                // TODO Auto-generated method stub
                String code = editBarcode.getText().toString();
                if (code.matches("")) //{ if(code.trim().isEmpty())
                //|| editBarcode.getText().toString() > 100 )
                {
                    Log.d(TAG, "Code ist leer");
                }


                if (keyCode == KeyEvent.KEYCODE_ENTER && code.length() > 0) {
                    editBarcode.setText("");
                    ScanService.checkEnteredCode(code);
                    return true;
                }
                return false;
            }
        });

        recyclerView = findViewById(R.id.recyclerview);
        recyclerviewAdapter = new RecyclerviewAdapter(this);
        Intent newIntent = getIntent();
        String receivedPalNo =  newIntent.getStringExtra("palNo");
        String receivedNo =  newIntent.getStringExtra("no");
        String receivedType =  newIntent.getStringExtra("type");
        String receivedRack =  newIntent.getStringExtra("rack");
        String receivedCountItems =  newIntent.getStringExtra("count_items");
        content.setText(receivedCountItems);
        RestClient.getPaletteItems(getApplicationContext(),recyclerviewAdapter,receivedPalNo);

        Log.d(TAGG,"Intent 1" + receivedPalNo);
        Log.d(TAGG, "Intent 2" + receivedNo);
        Log.d(TAGG, "Intent 3" + receivedType);
        Log.d(TAGG,"Intent 4" + receivedRack);
        Log.d(TAGG, "Intent 5" + receivedCountItems);

        final ArrayList<Items> itemList = new ArrayList<>();
        /*
        Items[] items = new Items(12345,123456, 200, 500);
        itemList.add(items);*/


        recyclerviewAdapter.setItemList((ArrayList<Items>) itemList);
        recyclerView.setAdapter(recyclerviewAdapter);

        touchListener = new RecyclerTouchListener(this,recyclerView);
        RecyclerviewAdapter finalRecyclerviewAdapter = recyclerviewAdapter;
        touchListener
                .setClickable(new RecyclerTouchListener.OnRowClickListener() {
                    @Override
                    public void onRowClicked(int position) {
                        //Toast.makeText(getApplicationContext(),itemList.get(position), Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onIndependentViewClicked(int independentViewID, int position) {

                    }
                })
                .setSwipeOptionViews(R.id.delete_task,R.id.edit_task)
                .setSwipeable(R.id.rowFG, R.id.rowBG, new RecyclerTouchListener.OnSwipeOptionsClickListener() {
                    @Override
                    public void onSwipeOptionClicked(int viewID, int position) {
                        switch (viewID){
                            case R.id.delete_task:
                                itemList.remove(position);
                                finalRecyclerviewAdapter.setItemList(itemList);
                                break;
                            case R.id.edit_task:
                                Toast.makeText(getApplicationContext(),"Edit Not Available",Toast.LENGTH_SHORT).show();
                                break;

                        }
                    }
                });
        recyclerView.addOnItemTouchListener(touchListener);



        class StableArrayAdapter extends ArrayAdapter<String> {

            HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

            public StableArrayAdapter(Context context, int textViewResourceId,
                                      List<String> objects) {
                super(context, textViewResourceId, objects);
                for (int i = 0; i < objects.size(); ++i) {
                    mIdMap.put(objects.get(i), i);
                }
            }

            @Override
            public long getItemId(int position) {
                String item = getItem(position);
                return mIdMap.get(item);
            }

            @Override
            public boolean hasStableIds() {
                return true;
            }

        }

    // savedInstanceState is non-null when there is fragment state
        // saved from previous configurations of this activity
        // (e.g. when rotating the screen from portrait to landscape).
        // In this case, the fragment will automatically be re-added
        // to its container so we don"t need to manually add it.
        // For more information, see the Fragments API guide at:
        //
        // http://developer.android.com/guide/components/fragments.html
        //
        String text = getIntent().getStringExtra("palNo");
        //headerView.setText(text);

        if (receivedType != null && receivedType.equals("FE")) {
            ImageView mImgView = findViewById(R.id.id_col_code);
            mImgView.setBackgroundResource(R.drawable.backgroun_blue);
        }
        if (receivedType != null && receivedType.equals("UFE")) {
            ImageView mImgView = findViewById(R.id.id_col_code);
            mImgView.setBackgroundResource(R.drawable.backgroun_yellow);
        }

    }

    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    public boolean onMenuItemClick(MenuItem item) {
        Toast.makeText(this, "Selected Item: " +item.getTitle(), Toast.LENGTH_SHORT).show();
        switch (item.getItemId()) {
            case R.id.search_item:
                // do your code
                return true;
            case R.id.upload_item:
                // do your code
                return true;
            case R.id.copy_item:
                // do your code
                return true;
           /* case R.id.print_item:
                // do your code
                return true;*/
            case R.id.share_item:
                // do your code
                return true;
            /*case R.id.bookmark_item:
                // do your code
                return true;*/
            default:
                return false;
        }
    }


        public void newDialog(Activity activity) {
            final Dialog dialog = new Dialog(activity);
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setCancelable(true);
            dialog.setContentView(R.layout.sortiment_layout);
            dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));

            Button okButton = dialog.findViewById(R.id.ok);
            okButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //Toast.makeText(getApplicationContext(),"Ok" ,Toast.LENGTH_SHORT).show();
                    dialog.dismiss();
                }
            });
            Button cancelButton = dialog.findViewById(R.id.cancel);
            cancelButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //Toast.makeText(getApplicationContext(),"Abbrechen" ,Toast.LENGTH_SHORT).show();
                    dialog.cancel();
                }
            });
            dialog.show();
        }

        public void showDialog(Activity activity) {
            final Dialog dialog = new Dialog(activity);
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setCancelable(true);
            dialog.setContentView(R.layout.newcustom_layout);
            dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));


            Button okButton = dialog.findViewById(R.id.ok);
            okButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //Toast.makeText(getApplicationContext(),"Ok" ,Toast.LENGTH_SHORT).show();
                    dialog.dismiss();
                }
            });
            dialog.show();
        }


    public void onItemSelected(AdapterView<?> parent, View view,
                               int pos, long id) {
        // An item was selected. You can retrieve the selected item using
        // parent.getItemAtPosition(pos)
    }

    public void onNothingSelected(AdapterView<?> parent) {
        // Another interface callback
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            // This ID represents the Home or Up button. In the case of this
            // activity, the Up button is shown. For
            // more details, see the Navigation pattern on Android Design:
            //
            // http://developer.android.com/design/patterns/navigation.html#up-vs-back
            //
            navigateUpTo(new Intent(this, MainListActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onResume() {
        super.onResume();
        recyclerView.addOnItemTouchListener(touchListener);
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }
}

The ScanService Class: ScanService Class:

package com.example.xxx;

import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.TextView;


public class ScanService {


    private static final String TAG = "Scan Service Tag";
    private static Context mContext;
    private static Activity a = (MainDetailActivity)mContext;
    private static TextView content = (TextView) 
    a.findViewById(R.id.content_detail);
    private static TextView editTextNumber = (TextView) 
    a.findViewById(R.id.editTextNumber);

    public ScanService (Context mContext) {
        this.mContext = mContext;
    }

    public static void checkEnteredCode(String code, Activity a) {
        content.setText("");

        //PSP-H1-EA-F3
        if
        (code.matches("PSP-\\p{Upper}\\d\\p{Punct}\\p{Upper}\\" +
                "p{Upper}\\p{Punct}\\p{Upper}\\p{Digit}")) {
            content.setText("");
            content.setText(code);
            Log.d(TAG, "xxx");

        }
        if (code.matches("LF-[0-9]*")) {
            ///LF-(\d+)/gi
            content.setText("");
            content.setText(code);
            Log.d(TAG, "xxx");
        }
        if (code.matches("PAL-[0-9][0-9][0-9]")) {

            content.setText("");
            content.setText(code);
            Log.d(TAG, "xxx");
        }
        if (code.matches("P-[0-9][0-9][0-9]")) {

            content.setText("");
            content.setText(code);
            Log.d(TAG, "Palette");
        }
        if (code.matches("[0-9][0-9][0-9][0-9].[0-9][0-9].+DB")) {
           
            if(editTextNumber == null) {
                Log.d(TAG, "xxx");
            }
            else {
                editTextNumber.setText(code);
                Log.d(TAG, "xxx");
            }
            Log.d(TAG, "xxx");
        }
        if (code.matches("[0-9A-Z]*[0-9]*")) {
            //editBarcode.setText("");
            //editBarcode.setText(keyCode);
            Log.d(TAG, "xxx");
        }
        if (code.matches("\\d{13}")) {
            //newDialog(MainDetailActivity.this);
            //editBarcode.setText("");
            //editBarcode.setText(keyCode);
            if(editTextNumber == null) {
                Log.d(TAG, "xxx");
            }
            else {
                editTextNumber.setText(code);
                Log.d(TAG, "xxx");
            }
            Log.d(TAG, "xxx");
        }
        else {
            Log.d(TAG, "xxx");

        };
        //editBarcode.setText("");
        //editBarcode.setText(code);
            /* String code = editBarcode.getText().toString();
                if (code.matches("")) //{ if(code.trim().isEmpty())
                //|| editBarcode.getText().toString() > 100 )
                {
                    Log.d(TAG, "xxx");
                }
                //}
                checkEnteredCode(code);
                //editBarcode.setText("");
             return Boolean.parseBoolean(code);*/
        Log.d(TAG, code);

    }

    public static void checkEnteredCode(String code) {
    }
}

You cannot access any View s from a Service !您不能从Service访问任何View View s belong to the Activity . View属于Activity This is the wrong application architecture.这是错误的应用程序架构。 A Service performs background processing (file I/O, network I/O, computation, etc.). Service执行后台处理(文件 I/O、网络 I/O、计算等)。 The Activity is responsible for interacting with the user (inputs, display, etc.). Activity负责与用户交互(输入、显示等)。 If your Service wants to put data on the screen, you've broken the division of responsibilities.如果您的Service想要将数据显示在屏幕上,那么您已经打破了职责分工。 Your Service should simply notify your Activity (or any other component that is interested) when data has changed, and the Activity can then update the View itself.当数据发生变化时,您的Service应该简单地通知您的Activity (或任何其他感兴趣的组件),然后Activity可以更新View本身。 You can share data between the Service and your other components in a number of ways, including: event bus, publish/subscribe, shared preferences, broadcast Intent s, SQLite database, etc.您可以通过多种方式在Service和您的其他组件之间共享数据,包括:事件总线、发布/订阅、共享首选项、广播Intent 、SQLite 数据库等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM